mirror of
https://github.com/apple/swift.git
synced 2026-10-22 19:15:50 +02:00
The previous implementation did not work in all CFG configurations, and would take some effort to do so. We don't have an immediate need to support OSSA form with this pass, so we don't need to precisely place `store_borrow` and `end_borrow` scopes, and `alloc_stack`/`dealloc_stack` can be placed with less precision so long as they balance, and type-dependent stack allocations are dominated by the def for the type.
239 lines
9.3 KiB
Plaintext
239 lines
9.3 KiB
Plaintext
// RUN: %target-sil-opt -enable-sil-verify-all %s -loadable-address | %FileCheck %s
|
|
|
|
import Builtin
|
|
import Swift
|
|
|
|
public struct BigArc { var a, b, c, d, e: AnyObject }
|
|
|
|
public struct BiggerArc { var bigArc: BigArc }
|
|
|
|
sil @makeBigArc : $@convention(thin) () -> BigArc
|
|
sil @takeBorrowBigArc : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
|
|
// In test1, `%1` is a `BigArc` that will already become indirected because
|
|
// it is the result of a function call that will become an indirect return.
|
|
// `make_borrow` of the value becomes `make_borrow_addr` of the value's
|
|
// lowered memory address.
|
|
|
|
// CHECK-LABEL: sil @test1
|
|
// CHECK: apply {{%.*}}([[OUT:%[0-9]+]])
|
|
// CHECK: make_addr_borrow [[OUT]]
|
|
sil @test1 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = function_ref @makeBigArc : $@convention(thin) () -> BigArc
|
|
%1 = apply %0() : $@convention(thin) () -> BigArc
|
|
%2 = make_borrow %1
|
|
%3 = struct $Ref<BigArc> (%2)
|
|
%4 = function_ref @takeBorrowBigArc : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
%5 = apply %4(%3) : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
%6 = tuple ()
|
|
return %6
|
|
}
|
|
|
|
// In test2, `%4` is a `BigArc` that is `load`-ed from a memory location.
|
|
// `make_borrow` of the load becomes `make_borrow_addr` of the loaded address.
|
|
|
|
// CHECK-LABEL: sil @test2
|
|
// CHECK: apply {{%.*}}([[OUT:%[0-9]+]])
|
|
// CHECK: copy_addr [take] [[OUT]] to [init] [[LOCAL:%[0-9]+]]
|
|
// CHECK: make_addr_borrow [[LOCAL]]
|
|
sil @test2 : $@convention(thin) () -> () {
|
|
bb0:
|
|
%0 = alloc_stack $BigArc
|
|
%1 = function_ref @makeBigArc : $@convention(thin) () -> BigArc
|
|
%2 = apply %1() : $@convention(thin) () -> BigArc
|
|
store %2 to %0
|
|
%4 = load %0
|
|
%5 = make_borrow %4
|
|
%6 = struct $Ref<BigArc> (%5)
|
|
%7 = function_ref @takeBorrowBigArc : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
%8 = apply %7(%6) : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
destroy_addr %0
|
|
dealloc_stack %0
|
|
%11 = tuple ()
|
|
return %11
|
|
}
|
|
|
|
|
|
// In test3, `%5` is a `BigArc` that is formed locally and doesn't directly
|
|
// pass through any function boundaries. `make_borrow` of the local value
|
|
// becomes `make_addr_borrow` of a temporary allocation.
|
|
|
|
// CHECK-LABEL: sil @test3
|
|
// CHECK: [[BUF:%.*]] = alloc_stack
|
|
// CHECK: [[BIGARC:%.*]] = struct $BigArc
|
|
// CHECK: store [[BIGARC]] to [[BUF]]
|
|
// CHECK: [[B_BORROW:%.*]] = make_addr_borrow [[BUF]]
|
|
// CHECK: [[S_BORROW:%.*]] = struct $Ref<BigArc> ([[B_BORROW]])
|
|
// CHECK: apply {{.*}}([[S_BORROW]])
|
|
// CHECK: release_value [[BIGARC]]
|
|
// CHECK: dealloc_stack [[BUF]]
|
|
sil @test3 : $@convention(thin) (@owned AnyObject) -> () {
|
|
bb0(%0 : $AnyObject):
|
|
retain_value %0
|
|
retain_value %0
|
|
retain_value %0
|
|
retain_value %0
|
|
|
|
%5 = struct $BigArc(%0, %0, %0, %0, %0)
|
|
%6 = make_borrow %5
|
|
%7 = struct $Ref<BigArc> (%6)
|
|
%8 = function_ref @takeBorrowBigArc : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
%9 = apply %8(%7) : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
release_value %5
|
|
%11 = tuple ()
|
|
return %11
|
|
}
|
|
|
|
// In test4, `%1` is a `BigArc` that is projected from a `BiggerArc` that
|
|
// is passed in by value and will be turned into an indirect parameter by
|
|
// the pass.
|
|
|
|
// CHECK-LABEL: sil @test4
|
|
// CHECK: bb0([[PARAM:%.*]] : $*BiggerArc):
|
|
// CHECK: [[BIGARC_ADDR:%.*]] = struct_element_addr [[PARAM]]
|
|
// CHECK: [[BORROW:%.*]] = make_addr_borrow [[BIGARC_ADDR]]
|
|
sil @test4 : $@convention(thin) (@guaranteed BiggerArc) -> () {
|
|
bb0(%0 : $BiggerArc):
|
|
%1 = struct_extract %0, #BiggerArc.bigArc
|
|
%2 = make_borrow %1
|
|
%3 = struct $Ref<BigArc> (%2)
|
|
%4 = function_ref @takeBorrowBigArc : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
%5 = apply %4(%3) : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
%6 = tuple ()
|
|
return %6
|
|
}
|
|
|
|
// In test5, `%7` is a `BigArc` that is projected from a `BiggerArc` that
|
|
// is formed locally.
|
|
|
|
// CHECK-LABEL: sil @test5
|
|
// CHECK: [[BUF:%.*]] = alloc_stack
|
|
// CHECK: [[BIGARC:%.*]] = struct_extract {{%.*}}, #BiggerArc.bigArc
|
|
// CHECK: store [[BIGARC]] to [[BUF]]
|
|
// CHECK: [[B_BORROW:%.*]] = make_addr_borrow [[BUF]]
|
|
// CHECK: [[S_BORROW:%.*]] = struct $Ref<BigArc> ([[B_BORROW]])
|
|
// CHECK: apply {{.*}}([[S_BORROW]])
|
|
// CHECK: release_value [[BIGARC]]
|
|
// CHECK: dealloc_stack [[BUF]]
|
|
sil @test5 : $@convention(thin) (@owned AnyObject) -> () {
|
|
bb0(%0 : $AnyObject):
|
|
retain_value %0
|
|
retain_value %0
|
|
retain_value %0
|
|
retain_value %0
|
|
|
|
%5 = struct $BigArc(%0, %0, %0, %0, %0)
|
|
%6 = struct $BiggerArc(%5)
|
|
|
|
%7 = struct_extract %6, #BiggerArc.bigArc
|
|
%8 = make_borrow %7
|
|
%9 = struct $Ref<BigArc> (%8)
|
|
%10 = function_ref @takeBorrowBigArc : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
%11 = apply %10(%9) : $@convention(thin) (@guaranteed Ref<BigArc>) -> ()
|
|
release_value %7
|
|
%13 = tuple ()
|
|
return %13
|
|
}
|
|
|
|
public struct OneArcGen<T> { var a: AnyObject }
|
|
public struct BigArcGen<T> { var a, b, c, d, e: OneArcGen<T> }
|
|
|
|
sil @takeBorrowBigArcGen : $@convention(thin) <T> (@guaranteed Ref<BigArcGen<T>>) -> ()
|
|
|
|
protocol P {
|
|
static func makeBigArc() -> OneArcGen<Self>
|
|
}
|
|
|
|
// In test6, `%x` is a `BigArc<T>` that is formed dependent on an opened
|
|
// existential which does not pass through any function boundaries.
|
|
// `make_borrow` of the local value becomes `make_addr_borrow` of a temporary
|
|
// allocation.
|
|
|
|
// CHECK-LABEL: sil @test6
|
|
// CHECK: open_existential
|
|
// CHECK: [[BUF:%.*]] = alloc_stack
|
|
// CHECK: [[BIGARC:%.*]] = struct $BigArc
|
|
// CHECK: store [[BIGARC]] to [[BUF]]
|
|
// CHECK: [[B_BORROW:%.*]] = make_addr_borrow [[BUF]]
|
|
// CHECK: [[S_BORROW:%.*]] = struct $Ref<BigArcGen<{{.*}}>> ([[B_BORROW]])
|
|
// CHECK: apply {{.*}}([[S_BORROW]])
|
|
// CHECK: release_value [[BIGARC]]
|
|
// CHECK: dealloc_stack [[BUF]]
|
|
sil @test6 : $@convention(thin) (@thick any P.Type) -> () {
|
|
bb0(%0 : $@thick any P.Type):
|
|
%1 = open_existential_metatype %0 to $@thick (@opened("00000000-0000-0000-0000-000000000000", any P) Self).Type
|
|
%2 = witness_method $@opened("00000000-0000-0000-0000-000000000000", any P) Self, #P.makeBigArc : <Self: P> (Self.Type) -> () -> OneArcGen<Self> : $@convention(witness_method : P) <Self: P> (@thick Self.Type) -> @owned OneArcGen<Self>
|
|
%3 = apply %2<@opened("00000000-0000-0000-0000-000000000000", any P) Self>(%1) : $@convention(witness_method : P) <Self: P> (@thick Self.Type) -> @owned OneArcGen<Self>
|
|
|
|
retain_value %3
|
|
retain_value %3
|
|
retain_value %3
|
|
retain_value %3
|
|
|
|
%8 = struct $BigArcGen<@opened("00000000-0000-0000-0000-000000000000", any P) Self>(%3, %3, %3, %3, %3)
|
|
%9 = make_borrow %8
|
|
%10 = struct $Ref<BigArcGen<@opened("00000000-0000-0000-0000-000000000000", any P) Self>> (%9)
|
|
%11 = function_ref @takeBorrowBigArcGen : $@convention(thin) <T> (@guaranteed Ref<BigArcGen<T>>) -> ()
|
|
%12 = apply %11<@opened("00000000-0000-0000-0000-000000000000", any P) Self>(%10) : $@convention(thin) <T> (@guaranteed Ref<BigArcGen<T>>) -> ()
|
|
release_value %8
|
|
%14 = tuple ()
|
|
return %14
|
|
}
|
|
|
|
// In test7, `%x` is a `BigArc<T>` that is formed dependent on an opened
|
|
// existential which does not pass through any function boundaries, and which
|
|
// is only used on one branch of a divergent control flow.
|
|
// `make_borrow` of the local value becomes `make_addr_borrow` of a temporary
|
|
// allocation.
|
|
|
|
// CHECK-LABEL: sil @test7
|
|
// CHECK: cond_br {{.*}}, [[YES:bb[0-9]+]], [[NO:bb[0-9]+]]
|
|
// CHECK: [[YES]]:
|
|
// CHECK: open_existential
|
|
// CHECK: [[BUF:%.*]] = alloc_stack
|
|
// CHECK: br [[YES2:bb[0-9]+]]
|
|
// CHECK: [[YES2]]:
|
|
// CHECK: [[BIGARC:%.*]] = struct $BigArcGen
|
|
// CHECK: store [[BIGARC]] to [[BUF]]
|
|
// CHECK: [[B_BORROW:%.*]] = make_addr_borrow [[BUF]]
|
|
// CHECK: [[S_BORROW:%.*]] = struct $Ref<BigArcGen<{{.*}}>> ([[B_BORROW]])
|
|
// CHECK: apply {{.*}}([[S_BORROW]])
|
|
// CHECK: release_value [[BIGARC]]
|
|
// CHECK: dealloc_stack [[BUF]]
|
|
// CHECK: br [[CONT:bb[0-9]+]]
|
|
// CHECK: [[NO]]:
|
|
// CHECK: br [[CONT]]
|
|
sil @test7 : $@convention(thin) (@thick any P.Type, Builtin.Int1) -> () {
|
|
bb0(%0 : $@thick any P.Type, %1 : $Builtin.Int1):
|
|
cond_br %1, bb1, bb3
|
|
|
|
bb1:
|
|
%3 = open_existential_metatype %0 to $@thick (@opened("00000001-0000-0000-0000-000000010000", any P) Self).Type
|
|
%4 = witness_method $@opened("00000001-0000-0000-0000-000000010000", any P) Self, #P.makeBigArc : <Self: P> (Self.Type) -> () -> OneArcGen<Self> : $@convention(witness_method : P) <Self: P> (@thick Self.Type) -> @owned OneArcGen<Self>
|
|
%5 = apply %4<@opened("00000001-0000-0000-0000-000000010000", any P) Self>(%3) : $@convention(witness_method : P) <Self: P> (@thick Self.Type) -> @owned OneArcGen<Self>
|
|
br bb2
|
|
|
|
bb2:
|
|
retain_value %5
|
|
retain_value %5
|
|
retain_value %5
|
|
retain_value %5
|
|
|
|
%10 = struct $BigArcGen<@opened("00000001-0000-0000-0000-000000010000", any P) Self>(%5, %5, %5, %5, %5)
|
|
%11 = make_borrow %10
|
|
%12 = struct $Ref<BigArcGen<@opened("00000001-0000-0000-0000-000000010000", any P) Self>> (%11)
|
|
%13 = function_ref @takeBorrowBigArcGen : $@convention(thin) <T> (@guaranteed Ref<BigArcGen<T>>) -> ()
|
|
%14 = apply %13<@opened("00000001-0000-0000-0000-000000010000", any P) Self>(%12) : $@convention(thin) <T> (@guaranteed Ref<BigArcGen<T>>) -> ()
|
|
release_value %10
|
|
br bb4
|
|
|
|
bb3:
|
|
br bb4
|
|
|
|
bb4:
|
|
%16 = tuple ()
|
|
return %16
|
|
}
|
|
|