> On Dec 6, 2016, at 11:29 AM, John McCall <rjmcc...@apple.com> wrote: > >> On Dec 6, 2016, at 10:17 AM, Joe Groff via swift-dev <swift-dev@swift.org> >> wrote: >>> On Dec 5, 2016, at 4:24 PM, Michael Gottesman via swift-dev >>> <swift-dev@swift.org> wrote: >>> >>> Hello everyone! >>> >>> This is a proposal for 2 instructions needed to express borrowing via SSA >>> at the SIL level. The need for these were discovered while I was >>> prototyping a SIL ownership verifier. >>> >>> A html version of the proposal: >>> >>> https://gottesmm.github.io/proposals/sil-ownership-value-ssa-operations.html >>> >>> And inline: >>> >>> ---- >>> >>> # Summary >>> >>> This document proposes the addition of the following new SIL instructions: >>> >>> 1. `store_borrow` >>> 2. `begin_borrow` >>> >>> These enable the expression of the following operations in Semantic SIL: >>> >>> 1. Passing an `@guaranteed` value to an `@in_guaranteed` argument without >>> performing a copy. (`store_borrow`) >>> 2. Copying a field from an `@owned` aggregate without consuming or copying >>> the entire >>> aggregate. (`begin_borrow`) >>> 3. Passing an `@owned` value as an `@guaranteed` argument parameter. >>> >>> # Definitions >>> >>> ## store_borrow >>> >>> Define `store_borrow` as: >>> >>> store_borrow %x to %y : $*T >>> ... >>> end_borrow %y from %x : $*T, $T >>> >>> => >>> >>> store %x to %y >>> >>> `store_borrow` is needed to convert `@guaranteed` values to `@in_guaranteed` >>> arguments. Without a `store_borrow`, this can only be expressed via an >>> inefficient `copy_value` + `store` + `load` + `destroy_value` sequence: >>> >>> sil @g : $@convention(thin) (@in_guaranteed Foo) -> () >>> >>> sil @f : $@convention(thin) (@guaranteed Foo) -> () { >>> bb0(%0 : $Foo): >>> %1 = function_ref @g : $@convention(thin) (@in_guaranteed Foo) -> () >>> %2 = alloc_stack $Foo >>> %3 = copy_value %0 : $Foo >>> store %3 to [init] %2 : $Foo >>> apply %1(%2) : $@convention(thin) (@in_guaranteed Foo) -> () >>> %4 = load [take] %2 : $*Foo >>> destroy_value %4 : $Foo >>> dealloc_stack %2 : $Foo >>> ... >>> } >>> >>> `store_borrow` allows us to express this in a more efficient and expressive >>> SIL: >>> >>> sil @f : $@convention(thin) (@guaranteed Foo) -> () { >>> bb0(%0 : $Foo): >>> %1 = function_ref @g : $@convention(thin) (@in_guaranteed Foo) -> () >>> %2 = alloc_stack $Foo >>> store_borrow %0 to %2 : $*T >>> apply %1(%2) : $@convention(thin) (@in_guaranteed Foo) -> () >>> end_borrow %2 from %0 : $*T, $T >>> dealloc_stack %2 : $Foo >>> ... >>> } >>> >>> **NOTE** Once `@in_guaranteed` arguments become passed as values, >>> `store_borrow` >>> will no longer be necessary. >>> >>> ## begin_borrow >>> >>> Define a `begin_borrow` instruction as: >>> >>> %borrowed_x = begin_borrow %x : $T >>> %borrow_x_field = struct_extract %borrowed_x : $T, #T.field >>> apply %f(%borrowed_x) : $@convention(thin) (@guaranteed T) -> () >>> end_borrow %borrowed_x from %x : $T, $T >>> >>> => >>> >>> %x_field = struct_extract %x : $T, #T.field >>> apply %f(%x_field) : $@convention(thin) (@guaranteed T) -> () >>> >>> A `begin_borrow` instruction explicitly converts an `@owned` value to a >>> `@guaranteed` value. The result of the `begin_borrow` is paired with an >>> `end_borrow` instruction that explicitly represents the end scope of the >>> `begin_borrow`. >>> >>> `begin_borrow` also allows for the explicit borrowing of an `@owned` value >>> for >>> the purpose of passing the value off to an `@guaranteed` parameter. >>> >>> *NOTE* Alternatively, we could make it so that *_extract operations started >>> borrow scopes, but this would make SIL less explicit from an ownership >>> perspective since one wouldn't be able to visually identify the first >>> `struct_extract` in a chain of `struct_extract`. In the case of >>> `begin_borrow`, >>> there is no question and it is completely explicit. >> >> begin_borrow SGTM. Does end_borrow need to be explicit, or could we leave it >> implicit and rely on dataflow diagnostics to ensure the borrowed value's >> lifetime is dominated by the owner's? It seems to me like, even if >> end_borrow is explicit, we'd want a lifetime-shortening pass to shrinkwrap >> end_borrows to the precise lifetime of the borrowed value's uses. > > I definitely think it should be explicit, as Michael has it. > > Michael, does store_borrow go away if/when we eliminate the need for > different code patterns for direct vs. indirect arguments?
Yes. > > John. _______________________________________________ swift-dev mailing list swift-dev@swift.org https://lists.swift.org/mailman/listinfo/swift-dev