Skip to content

Commit

Permalink
[semantic-sil] When calling emitRValueForDecl, borrow the value befor…
Browse files Browse the repository at this point in the history
…e deciding whether or not to copy the value.

rdar://29791263
  • Loading branch information
gottesmm committed Feb 15, 2017
1 parent 58c3959 commit d4ae7a3
Show file tree
Hide file tree
Showing 67 changed files with 1,408 additions and 628 deletions.
3 changes: 2 additions & 1 deletion lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,8 @@ emitRValueForDecl(SILLocation loc, ConcreteDeclRef declRef, Type ncRefType,
refType, emitManagedRValueWithCleanup(Scalar));
}

auto Result = ManagedValue::forUnmanaged(Scalar);
// This is a let, so we can make guarantees, so begin the borrow scope.
ManagedValue Result = emitManagedBeginBorrow(loc, Scalar);

// If the client can't handle a +0 result, retain it to get a +1.
// This is a 'let', so we can make guarantees.
Expand Down
47 changes: 25 additions & 22 deletions test/SILGen/accessors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,19 @@ func test0(_ ref: A) {
// CHECK: bb0([[ARG:%.*]] : $A):
// CHECK-NEXT: debug_value
// Formal evaluation of LHS.
// CHECK-NEXT: [[BORROWED_ARG_LHS:%.*]] = begin_borrow [[ARG]]
// CHECK-NEXT: // function_ref accessors.index0 () -> Swift.Int
// CHECK-NEXT: [[T0:%.*]] = function_ref @_T09accessors6index0SiyF
// CHECK-NEXT: [[INDEX0:%.*]] = apply [[T0]]()
// Formal evaluation of RHS.
// CHECK-NEXT: [[BORROWED_ARG_RHS:%.*]] = begin_borrow [[ARG]]
// CHECK-NEXT: // function_ref accessors.index1 () -> Swift.Int
// CHECK-NEXT: [[T0:%.*]] = function_ref @_T09accessors6index1SiyF
// CHECK-NEXT: [[INDEX1:%.*]] = apply [[T0]]()
// Formal access to RHS.
// CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $OrdinarySub
// CHECK-NEXT: [[T0:%.*]] = class_method [[ARG]] : $A, #A.array!getter.1
// CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[ARG]])
// CHECK-NEXT: [[T0:%.*]] = class_method [[BORROWED_ARG_RHS]] : $A, #A.array!getter.1
// CHECK-NEXT: [[T1:%.*]] = apply [[T0]]([[BORROWED_ARG_RHS]])
// CHECK-NEXT: store [[T1]] to [init] [[TEMP]]
// CHECK-NEXT: [[T0:%.*]] = load [take] [[TEMP]]
// CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.getter : (Swift.Int) -> Swift.Int
Expand All @@ -49,15 +51,13 @@ func test0(_ ref: A) {
// Formal access to LHS.
// CHECK-NEXT: [[STORAGE:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
// CHECK-NEXT: [[BUFFER:%.*]] = alloc_stack $OrdinarySub
// CHECK-NEXT: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER]]
// CHECK-NEXT: [[T1:%.*]] = class_method [[BORROWED_ARG]] : $A, #A.array!materializeForSet.1
// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[T0]], [[STORAGE]], [[BORROWED_ARG]])
// CHECK-NEXT: [[T1:%.*]] = class_method [[BORROWED_ARG_LHS]] : $A, #A.array!materializeForSet.1
// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[T0]], [[STORAGE]], [[BORROWED_ARG_LHS]])
// CHECK-NEXT: [[T3:%.*]] = tuple_extract [[T2]] {{.*}}, 0
// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*OrdinarySub on %0 : $A
// CHECK-NEXT: end_borrow [[BORROWED_ARG]] from [[ARG]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*OrdinarySub on [[BORROWED_ARG_LHS]] : $A
// CHECK-NEXT: // function_ref accessors.OrdinarySub.subscript.setter : (Swift.Int) -> Swift.Int
// CHECK-NEXT: [[T0:%.*]] = function_ref @_T09accessors11OrdinarySubV9subscriptSiSicfs
// CHECK-NEXT: apply [[T0]]([[VALUE]], [[INDEX0]], [[ADDR]])
Expand All @@ -66,7 +66,8 @@ func test0(_ ref: A) {
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer):
// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout A, @thick A.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $A
// CHECK-NEXT: store %0 to [init] [[TEMP2]] : $*A
// SEMANTIC SIL TODO: This is an issue caused by the callback for materializeForSet in the class case taking the value as @inout when it should really take it as @guaranteed.
// CHECK-NEXT: store [[BORROWED_ARG_LHS]] to [init] [[TEMP2]] : $*A
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick A.Type
// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*OrdinarySub to $Builtin.RawPointer
// CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE]], [[TEMP2]], [[T0]])
Expand All @@ -77,8 +78,10 @@ func test0(_ ref: A) {
// CHECK-NEXT: dealloc_stack [[BUFFER]]
// CHECK-NEXT: dealloc_stack [[STORAGE]]
// CHECK-NEXT: dealloc_stack [[TEMP]]
// CHECK-NEXT: end_borrow [[BORROWED_ARG_RHS]] from [[ARG]]
// CHECK-NEXT: end_borrow [[BORROWED_ARG_LHS]] from [[ARG]]
// Balance out the +1 from the function parameter.
// CHECK-NEXT: destroy_value %0
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return

Expand All @@ -99,25 +102,25 @@ func test1(_ ref: B) {
// CHECK: bb0([[ARG:%.*]] : $B):
// CHECK-NEXT: debug_value
// Formal evaluation of LHS.
// CHECK-NEXT: [[BORROWED_ARG_LHS:%.*]] = begin_borrow [[ARG]]
// CHECK-NEXT: // function_ref accessors.index0 () -> Swift.Int
// CHECK-NEXT: [[T0:%.*]] = function_ref @_T09accessors6index0SiyF
// CHECK-NEXT: [[INDEX0:%.*]] = apply [[T0]]()
// Formal evaluation of RHS.
// CHECK-NEXT: [[BORROWED_ARG_RHS:%.*]] = begin_borrow [[ARG]]
// CHECK-NEXT: // function_ref accessors.index1 () -> Swift.Int
// CHECK-NEXT: [[T0:%.*]] = function_ref @_T09accessors6index1SiyF
// CHECK-NEXT: [[INDEX1:%.*]] = apply [[T0]]()
// Formal access to RHS.
// CHECK-NEXT: [[STORAGE:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
// CHECK-NEXT: [[BUFFER:%.*]] = alloc_stack $MutatingSub
// CHECK-NEXT: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER]]
// CHECK-NEXT: [[T1:%.*]] = class_method [[BORROWED_ARG]] : $B, #B.array!materializeForSet.1
// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[T0]], [[STORAGE]], [[BORROWED_ARG]])
// CHECK-NEXT: [[T1:%.*]] = class_method [[BORROWED_ARG_RHS]] : $B, #B.array!materializeForSet.1
// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[T0]], [[STORAGE]], [[BORROWED_ARG_RHS]])
// CHECK-NEXT: [[T3:%.*]] = tuple_extract [[T2]] {{.*}}, 0
// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on %0 : $B
// CHECK-NEXT: end_borrow [[BORROWED_ARG]] from [[ARG]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[BORROWED_ARG_RHS]] : $B
// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.getter : (Swift.Int) -> Swift.Int
// CHECK-NEXT: [[T0:%.*]] = function_ref @_T09accessors11MutatingSubV9subscriptSiSicfg : $@convention(method) (Int, @inout MutatingSub) -> Int
// CHECK-NEXT: [[VALUE:%.*]] = apply [[T0]]([[INDEX1]], [[ADDR]])
Expand All @@ -126,7 +129,7 @@ func test1(_ ref: B) {
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer):
// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store %0 to [init] [[TEMP2]] : $*B
// CHECK-NEXT: store [[BORROWED_ARG_RHS]] to [init] [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*MutatingSub to $Builtin.RawPointer
// CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE]], [[TEMP2]], [[T0]])
Expand All @@ -137,15 +140,13 @@ func test1(_ ref: B) {
// Formal access to LHS.
// CHECK-NEXT: [[STORAGE2:%.*]] = alloc_stack $Builtin.UnsafeValueBuffer
// CHECK-NEXT: [[BUFFER2:%.*]] = alloc_stack $MutatingSub
// CHECK-NEXT: [[BORROWED_ARG_2:%.*]] = begin_borrow [[ARG]]
// CHECK-NEXT: [[T0:%.*]] = address_to_pointer [[BUFFER2]]
// CHECK-NEXT: [[T1:%.*]] = class_method [[BORROWED_ARG_2]] : $B, #B.array!materializeForSet.1
// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[T0]], [[STORAGE2]], [[BORROWED_ARG_2]])
// CHECK-NEXT: [[T1:%.*]] = class_method [[BORROWED_ARG_LHS]] : $B, #B.array!materializeForSet.1
// CHECK-NEXT: [[T2:%.*]] = apply [[T1]]([[T0]], [[STORAGE2]], [[BORROWED_ARG_LHS]])
// CHECK-NEXT: [[T3:%.*]] = tuple_extract [[T2]] {{.*}}, 0
// CHECK-NEXT: [[OPT_CALLBACK:%.*]] = tuple_extract [[T2]] {{.*}}, 1
// CHECK-NEXT: [[T4:%.*]] = pointer_to_address [[T3]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on %0 : $B
// CHECK-NEXT: end_borrow [[BORROWED_ARG_2]] from [[ARG]]
// CHECK-NEXT: [[ADDR:%.*]] = mark_dependence [[T4]] : $*MutatingSub on [[BORROWED_ARG_LHS]] : $B
// CHECK-NEXT: // function_ref accessors.MutatingSub.subscript.setter : (Swift.Int) -> Swift.Int
// CHECK-NEXT: [[T0:%.*]] = function_ref @_T09accessors11MutatingSubV9subscriptSiSicfs : $@convention(method) (Int, Int, @inout MutatingSub) -> ()
// CHECK-NEXT: apply [[T0]]([[VALUE]], [[INDEX0]], [[ADDR]])
Expand All @@ -154,7 +155,7 @@ func test1(_ ref: B) {
// CHECK: [[WRITEBACK]]([[CALLBACK_ADDR:%.*]] : $Builtin.RawPointer):
// CHECK-NEXT: [[CALLBACK:%.*]] = pointer_to_thin_function [[CALLBACK_ADDR]] : $Builtin.RawPointer to $@convention(thin) (Builtin.RawPointer, @inout Builtin.UnsafeValueBuffer, @inout B, @thick B.Type) -> ()
// CHECK-NEXT: [[TEMP2:%.*]] = alloc_stack $B
// CHECK-NEXT: store %0 to [init] [[TEMP2]] : $*B
// CHECK-NEXT: store [[BORROWED_ARG_LHS]] to [init] [[TEMP2]] : $*B
// CHECK-NEXT: [[T0:%.*]] = metatype $@thick B.Type
// CHECK-NEXT: [[T1:%.*]] = address_to_pointer [[ADDR]] : $*MutatingSub to $Builtin.RawPointer
// CHECK-NEXT: apply [[CALLBACK]]([[T1]], [[STORAGE2]], [[TEMP2]], [[T0]])
Expand All @@ -166,8 +167,10 @@ func test1(_ ref: B) {
// CHECK-NEXT: dealloc_stack [[STORAGE2]]
// CHECK-NEXT: dealloc_stack [[BUFFER]]
// CHECK-NEXT: dealloc_stack [[STORAGE]]
// CHECK: end_borrow [[BORROWED_ARG_RHS]] from [[ARG]]
// CHECK: end_borrow [[BORROWED_ARG_LHS]] from [[ARG]]
// Balance out the +1 from the function parameter.
// CHECK-NEXT: destroy_value %0
// CHECK-NEXT: destroy_value [[ARG]]
// CHECK-NEXT: tuple ()
// CHECK-NEXT: return

Expand Down
7 changes: 5 additions & 2 deletions test/SILGen/argument_labels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ public class Foo {
}

// CHECK-LABEL: sil hidden @_T015argument_labels7testFoo{{[_0-9a-zA-Z]*}}F
// CHECK: bb0([[ARG0:%.*]] : $Foo,
func testFoo(foo: Foo, x: X, y: Y) {
// CHECK: class_method %0 : $Foo, #Foo.doSomething!1 : (Foo) -> (X, Y) -> ()
// CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
// CHECK: class_method [[BORROWED_ARG0]] : $Foo, #Foo.doSomething!1 : (Foo) -> (X, Y) -> ()
foo.doSomething(x: x, y: y)

// CHECK: class_method %0 : $Foo, #Foo.doSomethingElse!1 : (Foo) -> (X) -> ()
// CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
// CHECK: class_method [[BORROWED_ARG0]] : $Foo, #Foo.doSomethingElse!1 : (Foo) -> (X) -> ()
foo.doSomethingElse(x: x)
}

4 changes: 3 additions & 1 deletion test/SILGen/auto_closures.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ var false_ = Bool()
// CHECK-LABEL: sil hidden @_T013auto_closures05call_A8_closureAA4BoolVADyXKF : $@convention(thin) (@owned @callee_owned () -> Bool) -> Bool
func call_auto_closure(_ x: @autoclosure () -> Bool) -> Bool {
// CHECK: bb0([[CLOSURE:%.*]] : $@callee_owned () -> Bool):
// CHECK: [[CLOSURE_COPY:%.*]] = copy_value [[CLOSURE]]
// CHECK: [[BORROWED_CLOSURE:%.*]] = begin_borrow [[CLOSURE]]
// CHECK: [[CLOSURE_COPY:%.*]] = copy_value [[BORROWED_CLOSURE]]
// CHECK: [[RET:%.*]] = apply [[CLOSURE_COPY]]()
// CHECK: end_borrow [[BORROWED_CLOSURE]] from [[CLOSURE]]
// CHECK: destroy_value [[CLOSURE]]
// CHECK: return [[RET]]
return x()
Expand Down
36 changes: 25 additions & 11 deletions test/SILGen/boxed_existentials.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ func test_concrete_erasure(_ x: ClericalError) -> Error {
// CHECK: bb0([[ARG:%.*]] : $ClericalError):
// CHECK: [[EXISTENTIAL:%.*]] = alloc_existential_box $Error, $ClericalError
// CHECK: [[ADDR:%.*]] = project_existential_box $ClericalError in [[EXISTENTIAL]] : $Error
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]]
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]]
// CHECK: store [[ARG_COPY]] to [init] [[ADDR]] : $*ClericalError
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
// CHECK: destroy_value [[ARG]]
// CHECK: return [[EXISTENTIAL]] : $Error

Expand Down Expand Up @@ -56,15 +58,18 @@ func test_property(_ x: Error) -> String {
return x._domain
}
// CHECK-LABEL: sil hidden @_T018boxed_existentials13test_propertySSs5Error_pF
// CHECK: [[VALUE:%.*]] = open_existential_box %0 : $Error to $*[[VALUE_TYPE:@opened\(.*\) Error]]
// CHECK: bb0([[ARG:%.*]] : $Error):
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[VALUE:%.*]] = open_existential_box [[BORROWED_ARG]] : $Error to $*[[VALUE_TYPE:@opened\(.*\) Error]]
// FIXME: Extraneous copy here
// CHECK-NEXT: [[COPY:%[0-9]+]] = alloc_stack $[[VALUE_TYPE]]
// CHECK-NEXT: copy_addr [[VALUE]] to [initialization] [[COPY]] : $*[[VALUE_TYPE]]
// CHECK: [[METHOD:%.*]] = witness_method $[[VALUE_TYPE]], #Error._domain!getter.1
// -- self parameter of witness is @in_guaranteed; no need to copy since
// value in box is immutable and box is guaranteed
// CHECK: [[RESULT:%.*]] = apply [[METHOD]]<[[VALUE_TYPE]]>([[COPY]])
// CHECK: destroy_value %0
// CHECK: end_borrow [[BORROWED_ARG]] from [[ARG]]
// CHECK: destroy_value [[ARG]]
// CHECK: return [[RESULT]]

func test_property_of_lvalue(_ x: Error) -> String {
Expand All @@ -76,7 +81,8 @@ func test_property_of_lvalue(_ x: Error) -> String {
// CHECK: bb0([[ARG:%.*]] : $Error):
// CHECK: [[VAR:%.*]] = alloc_box ${ var Error }
// CHECK: [[PVAR:%.*]] = project_box [[VAR]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[ARG]] : $Error
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[ARG_COPY:%.*]] = copy_value [[BORROWED_ARG]] : $Error
// CHECK: store [[ARG_COPY]] to [init] [[PVAR]]
// CHECK: [[VALUE_BOX:%.*]] = load [copy] [[PVAR]]
// CHECK: [[VALUE:%.*]] = open_existential_box [[VALUE_BOX]] : $Error to $*[[VALUE_TYPE:@opened\(.*\) Error]]
Expand All @@ -97,7 +103,9 @@ extension Error {

// CHECK-LABEL: sil hidden @_T018boxed_existentials21test_extension_methodys5Error_pF
func test_extension_method(_ error: Error) {
// CHECK: [[VALUE:%.*]] = open_existential_box %0
// CHECK: bb0([[ARG:%.*]] : $Error):
// CHECK: [[BORROWED_ARG:%.*]] = begin_borrow [[ARG]]
// CHECK: [[VALUE:%.*]] = open_existential_box [[BORROWED_ARG]]
// CHECK: [[METHOD:%.*]] = function_ref
// CHECK-NOT: copy_addr
// CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
Expand All @@ -113,6 +121,8 @@ func plusOneError() -> Error { }

// CHECK-LABEL: sil hidden @_T018boxed_existentials31test_open_existential_semanticsys5Error_p_sAC_ptF
// GUARANTEED-LABEL: sil hidden @_T018boxed_existentials31test_open_existential_semanticsys5Error_p_sAC_ptF
// CHECK: bb0([[ARG0:%.*]]: $Error,
// GUARANTEED: bb0([[ARG0:%.*]]: $Error,
func test_open_existential_semantics(_ guaranteed: Error,
_ immediate: Error) {
var immediate = immediate
Expand All @@ -121,19 +131,23 @@ func test_open_existential_semantics(_ guaranteed: Error,
// GUARANTEED: [[IMMEDIATE_BOX:%.*]] = alloc_box ${ var Error }
// GUARANTEED: [[PB:%.*]] = project_box [[IMMEDIATE_BOX]]

// CHECK-NOT: copy_value %0
// CHECK: [[VALUE:%.*]] = open_existential_box %0
// CHECK-NOT: copy_value [[ARG0]]
// CHECK: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
// CHECK: [[VALUE:%.*]] = open_existential_box [[BORROWED_ARG0]]
// CHECK: [[METHOD:%.*]] = function_ref
// CHECK-NOT: copy_addr
// CHECK: apply [[METHOD]]<{{.*}}>([[VALUE]])
// CHECK-NOT: destroy_value %0
// CHECK: end_borrow [[BORROWED_ARG0]] from [[ARG0]]
// CHECK-NOT: destroy_value [[ARG0]]

// GUARANTEED-NOT: copy_value %0
// GUARANTEED: [[VALUE:%.*]] = open_existential_box [[GUARANTEED:%0]]
// GUARANTEED-NOT: copy_value [[ARG0]]
// GUARANTEED: [[BORROWED_ARG0:%.*]] = begin_borrow [[ARG0]]
// GUARANTEED: [[VALUE:%.*]] = open_existential_box [[BORROWED_ARG0]]
// GUARANTEED: [[METHOD:%.*]] = function_ref
// GUARANTEED: apply [[METHOD]]<{{.*}}>([[VALUE]])
// GUARANTEED: end_borrow [[BORROWED_ARG0]] from [[ARG0]]
// GUARANTEED-NOT: destroy_addr [[VALUE]]
// GUARANTEED-NOT: destroy_value [[GUARANTEED]]
// GUARANTEED-NOT: destroy_value [[ARG0]]
guaranteed.extensionMethod()

// CHECK: [[IMMEDIATE:%.*]] = load [copy] [[PB]]
Expand Down
Loading

0 comments on commit d4ae7a3

Please sign in to comment.