// RUN: %target-swift-emit-silgen -Xllvm -sil-print-types %s | %FileCheck %s func sequence() {} func copyOrThrow(value: T) throws -> T { return value } // CHECK-LABEL: @$s4main13copyIntoTupleyxxQp_txxQpRvzlF : $@convention(thin) (@pack_guaranteed Pack{repeat each T}) -> @pack_out Pack{repeat each T} { // CHECK: bb0([[OUT:%0]] : $*Pack{repeat each T}, [[IN:%1]] : $*Pack{repeat each T}): // CHECK-NEXT: debug_value // CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0 // CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1 // CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T} // CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word) // CHECK: bb1([[IDX:%.*]] : $Builtin.Word) // CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1 // CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb3, bb2 // CHECK: bb2: // CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat each T} // CHECK-NEXT: open_pack_element [[INDEX]] of at , shape $each T, uuid [[UUID:".*"]] // CHECK-NEXT: [[DEST_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of [[OUT]] : $*Pack{repeat each T} as $*@pack_element([[UUID]]) each T // CHECK-NEXT: [[SRC_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of [[IN]] : $*Pack{repeat each T} as $*@pack_element([[UUID]]) each T // CHECK-NEXT: copy_addr [[SRC_ELT_ADDR]] to [init] [[DEST_ELT_ADDR]] : $*@pack_element([[UUID]]) each T // CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word // CHECK-NEXT: br bb1([[NEXT_IDX]] : $Builtin.Word) // CHECK: bb3: // CHECK-NEXT: [[RET:%.*]] = tuple () // CHECK-NEXT: return [[RET]] : $() func copyIntoTuple(_ args: repeat each T) -> (repeat each T) { return (repeat each args) } // CHECK-LABEL: @$s4main20copyOrThrowIntoTupleyxxQp_txxQpKRvzlF : $@convention(thin) (@pack_guaranteed Pack{repeat each T}) -> (@pack_out Pack{repeat each T}, @error any Error) { // CHECK: bb0([[OUT:%0]] : $*Pack{repeat each T}, [[IN:%1]] : $*Pack{repeat each T}): // CHECK-NEXT: debug_value // CHECK-NEXT: debug_value // CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0 // CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1 // CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T} // CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word) // CHECK: bb1([[IDX:%.*]] : $Builtin.Word) // CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1 // CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb4, bb2 // CHECK: bb2: // CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat each T} // CHECK-NEXT: open_pack_element [[INDEX]] of at , shape $each T, uuid [[UUID:".*"]] // CHECK-NEXT: [[DEST_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of [[OUT]] : $*Pack{repeat each T} as $*@pack_element([[UUID]]) each T // CHECK-NEXT: [[SRC_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of [[IN]] : $*Pack{repeat each T} as $*@pack_element([[UUID]]) each T // FIXME: make this a borrow // CHECK-NEXT: [[TEMP:%.*]] = alloc_stack $@pack_element([[UUID]]) each T // CHECK-NEXT: copy_addr [[SRC_ELT_ADDR]] to [init] [[TEMP]] : $*@pack_element([[UUID]]) each T // CHECK-NEXT: // function_ref copyOrThrow // CHECK-NEXT: [[FN:%.*]] = function_ref @$s4main11copyOrThrow5valuexx_tKlF : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error any Error) // CHECK-NEXT: try_apply [[FN]]<@pack_element([[UUID]]) each T>([[DEST_ELT_ADDR]], [[TEMP]]) : $@convention(thin) <τ_0_0> (@in_guaranteed τ_0_0) -> (@out τ_0_0, @error any Error), normal bb3, error bb5 // CHECK: bb3{{.*}}: // CHECK-NEXT: destroy_addr [[TEMP]] : $*@pack_element([[UUID]]) each T // CHECK-NEXT: dealloc_stack [[TEMP]] : $*@pack_element([[UUID]]) each T // CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word // CHECK-NEXT: br bb1([[NEXT_IDX]] : $Builtin.Word) // CHECK: bb4: // CHECK-NEXT: [[RET:%.*]] = tuple () // CHECK-NEXT: return [[RET]] : $() // CHECK: bb5([[ERROR:%.*]] : @owned $any Error): // CHECK-NEXT: destroy_addr [[TEMP]] : $*@pack_element([[UUID]]) each T // CHECK-NEXT: dealloc_stack [[TEMP]] : $*@pack_element([[UUID]]) each T // Error-path loop to destroy the partial pack expansion prior to [[IDX]] // CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0 // CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1 // CHECK-NEXT: br bb6([[IDX]] : $Builtin.Word) // CHECK: bb6([[LAST_IDX:%.*]] : $Builtin.Word) // CHECK-NEXT: [[LAST_IDX_EQ_ZERO:%.*]] = builtin "cmp_eq_Word"([[LAST_IDX]] : $Builtin.Word, [[ZERO]] : $Builtin.Word) : $Builtin.Int1 // CHECK-NEXT: cond_br [[LAST_IDX_EQ_ZERO]], bb8, bb7 // CHECK: bb7: // CHECK-NEXT: [[DESTROY_IDX:%.*]] = builtin "sub_Word"([[LAST_IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word // CHECK-NEXT: [[DESTROY_INDEX:%.*]] = dynamic_pack_index [[DESTROY_IDX]] of $Pack{repeat each T} // CHECK-NEXT: open_pack_element [[DESTROY_INDEX]] of at , shape $each T, uuid [[DESTROY_UUID:".*"]] // CHECK-NEXT: [[DESTROY_ELT_ADDR:%.*]] = pack_element_get [[DESTROY_INDEX]] of [[OUT]] : $*Pack{repeat each T} as $*@pack_element([[DESTROY_UUID]]) each T // CHECK-NEXT: destroy_addr [[DESTROY_ELT_ADDR]] : $*@pack_element([[DESTROY_UUID]]) each T // CHECK-NEXT: br bb6([[DESTROY_IDX]] : $Builtin.Word) // CHECK: bb8: // CHECK-NEXT: throw [[ERROR]] : $any Error func copyOrThrowIntoTuple(_ args: repeat each T) throws -> (repeat each T) { return (repeat try copyOrThrow(value: each args)) } // CHECK-LABEL: @$s4main22callCopyAndDestructure1a1b1cySi_S2StF // Set up the result pack. // CHECK: [[RESULT_PACK:%.*]] = alloc_pack $Pack{Int, String, String} // CHECK-NEXT: [[R0:%.*]] = alloc_stack $Int // CHECK-NEXT: [[R0_IDX:%.*]] = scalar_pack_index 0 of $Pack{Int, String, String} // CHECK-NEXT: pack_element_set [[R0]] : $*Int into [[R0_IDX]] of [[RESULT_PACK]] : $*Pack{Int, String, String} // CHECK-NEXT: [[R1:%.*]] = alloc_stack $String // CHECK-NEXT: [[R1_IDX:%.*]] = scalar_pack_index 1 of $Pack{Int, String, String} // CHECK-NEXT: pack_element_set [[R1]] : $*String into [[R1_IDX]] of [[RESULT_PACK]] : $*Pack{Int, String, String} // CHECK-NEXT: [[R2:%.*]] = alloc_stack $String // CHECK-NEXT: [[R2_IDX:%.*]] = scalar_pack_index 2 of $Pack{Int, String, String} // CHECK-NEXT: pack_element_set [[R2]] : $*String into [[R2_IDX]] of [[RESULT_PACK]] : $*Pack{Int, String, String} // Set up the argument pack. // CHECK: [[ARG_PACK:%.*]] = alloc_pack $Pack{Int, String, String} // CHECK-NEXT: [[ARG0:%.*]] = alloc_stack $Int // CHECK-NEXT: store %0 to [trivial] [[ARG0]] : $*Int // CHECK-NEXT: [[ARG0_IDX:%.*]] = scalar_pack_index 0 of $Pack{Int, String, String} // CHECK-NEXT: pack_element_set [[ARG0]] : $*Int into [[ARG0_IDX]] of [[ARG_PACK]] : $*Pack{Int, String, String} // CHECK-NEXT: [[ARG1:%.*]] = alloc_stack $String // CHECK-NEXT: [[COPY1:%.*]] = copy_value %1 : $String // CHECK-NEXT: store [[COPY1]] to [init] [[ARG1]] : $*String // CHECK-NEXT: [[ARG1_IDX:%.*]] = scalar_pack_index 1 of $Pack{Int, String, String} // CHECK-NEXT: pack_element_set [[ARG1]] : $*String into [[ARG1_IDX]] of [[ARG_PACK]] : $*Pack{Int, String, String} // CHECK-NEXT: [[ARG2:%.*]] = alloc_stack $String // CHECK-NEXT: [[COPY2:%.*]] = copy_value %2 : $String // CHECK-NEXT: store [[COPY2]] to [init] [[ARG2]] : $*String // CHECK-NEXT: [[ARG2_IDX:%.*]] = scalar_pack_index 2 of $Pack{Int, String, String} // CHECK-NEXT: pack_element_set [[ARG2]] : $*String into [[ARG2_IDX]] of [[ARG_PACK]] : $*Pack{Int, String, String} // Perform the call. // CHECK-NEXT: // function_ref // CHECK-NEXT: [[FN:%.*]] = function_ref @$s4main13copyIntoTupleyxxQp_txxQpRvzlF // CHECK-NEXT: apply [[FN]]([[RESULT_PACK]], [[ARG_PACK]]) // Destroy the argument pack. // CHECK-NEXT: destroy_addr [[ARG2]] : $*String // CHECK-NEXT: dealloc_stack [[ARG2]] : $*String // CHECK-NEXT: destroy_addr [[ARG1]] : $*String // CHECK-NEXT: dealloc_stack [[ARG1]] : $*String // CHECK-NEXT: dealloc_stack [[ARG0]] : $*Int // CHECK-NEXT: dealloc_pack [[ARG_PACK]] : $*Pack{Int, String, String} // Load from the pack and bind the locals. // CHECK-NEXT: [[A:%.*]] = load [trivial] [[R0]] : $*Int // CHECK-NEXT: [[MV:%.*]] = move_value [var_decl] %39 : $Int // CHECK-NEXT: debug_value [[MV]] : $Int // CHECK-NEXT: [[B:%.*]] = load [take] [[R1]] : $*String // CHECK-NEXT: ignored_use [[B]] // CHECK-NEXT: [[C:%.*]] = load [take] [[R2]] : $*String // CHECK-NEXT: [[C_LIFETIME:%.*]] = move_value [var_decl] [[C]] // CHECK-NEXT: debug_value [[C_LIFETIME]] : $String // CHECK-NEXT: destroy_value [[B]] : $String // End of statement. // CHECK-NEXT: dealloc_stack [[R2]] : $*String // CHECK-NEXT: dealloc_stack [[R1]] : $*String // CHECK-NEXT: dealloc_stack [[R0]] : $*Int // CHECK-NEXT: dealloc_pack [[RESULT_PACK]] : $*Pack{Int, String, String} // Sequence marker. // CHECK-NEXT: // function_ref // CHECK-NEXT: [[SEQUENCE_FN:%.*]] = function_ref @$s4main8sequenceyyF // CHECK-NEXT: apply [[SEQUENCE_FN]]() // Leave the function. // CHECK-NEXT: destroy_value [[C_LIFETIME]] : $String // CHECK-NEXT: extend_lifetime [[MV]] : $Int // CHECK-NEXT: [[RET:%.*]] = tuple () // CHECK-NEXT: return [[RET]] : $() func callCopyAndDestructure(a: Int, b: String, c: String) { let (a,_,c) = copyIntoTuple(a, b, c) sequence() } // CHECK-LABEL: @$s4main15callCopyAndBind4argsyxxQp_tRvzlF // Set up the result pack to initialize the elements of the tuple // we're going to bind the local variable to. // CHECK: [[TUPLE:%.*]] = alloc_stack [lexical] [var_decl] $(repeat each T), let, name "result" // CHECK-NEXT: [[RESULT_PACK:%.*]] = alloc_pack $Pack{repeat each T} // CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0 // CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1 // CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T} // CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word) // CHECK: bb1([[IDX:%.*]] : $Builtin.Word) // CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1 // CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb3, bb2 // CHECK: bb2: // CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat each T} // CHECK-NEXT: open_pack_element [[INDEX]] of at , shape $each T, uuid [[UUID:".*"]] // CHECK-NEXT: [[ELT_ADDR:%.*]] = tuple_pack_element_addr [[INDEX]] of [[TUPLE]] : $*(repeat each T) as $*@pack_element([[UUID]]) each T // CHECK-NEXT: pack_element_set [[ELT_ADDR]] : $*@pack_element([[UUID]]) each T into [[INDEX]] of [[RESULT_PACK]] : $*Pack{repeat each T} // CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word // CHECK-NEXT: br bb1([[NEXT_IDX]] : $Builtin.Word) // CHECK: bb3: // Set up the argument pack with copies of the parameter pack. // CHECK-NEXT: [[ARG_PACK:%.*]] = alloc_pack $Pack{repeat each T} // CHECK-NEXT: [[ARG_TUPLE:%.*]] = alloc_stack $(repeat each T) // CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0 // CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1 // CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T} // CHECK-NEXT: br bb4([[ZERO]] : $Builtin.Word) // CHECK: bb4([[IDX:%.*]] : $Builtin.Word) // CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1 // CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb6, bb5 // CHECK: bb5: // CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat each T} // CHECK-NEXT: open_pack_element [[INDEX]] of at , shape $each T, uuid [[UUID:".*"]] // CHECK-NEXT: [[DEST_ADDR:%.*]] = tuple_pack_element_addr [[INDEX]] of [[ARG_TUPLE]] : $*(repeat each T) as $*@pack_element([[UUID]]) each T // CHECK-NEXT: [[SRC_ADDR:%.*]] = pack_element_get [[INDEX]] of %0 : $*Pack{repeat each T} as $*@pack_element([[UUID]]) each T // CHECK-NEXT: copy_addr [[SRC_ADDR]] to [init] [[DEST_ADDR]] : $*@pack_element([[UUID]]) each T // CHECK-NEXT: pack_element_set [[DEST_ADDR]] : $*@pack_element([[UUID]]) each T into [[INDEX]] of [[ARG_PACK]] : $*Pack{repeat each T} // CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word // CHECK-NEXT: br bb4([[NEXT_IDX]] : $Builtin.Word) // CHECK: bb6: // Perform the call. // CHECK-NEXT: // function_ref // CHECK-NEXT: [[FN:%.*]] = function_ref @$s4main13copyIntoTupleyxxQp_txxQpRvzlF // CHECK-NEXT: apply [[FN]]([[RESULT_PACK]], [[ARG_PACK]]) // End of statement. // CHECK-NEXT: destroy_addr [[ARG_TUPLE]] : $*(repeat each T) // CHECK-NEXT: dealloc_stack [[ARG_TUPLE]] : $*(repeat each T) // CHECK-NEXT: dealloc_pack [[ARG_PACK]] : $*Pack{repeat each T} // CHECK-NEXT: dealloc_pack [[RESULT_PACK]] : $*Pack{repeat each T} // Sequence point. // CHECK-NEXT: // function_ref // CHECK-NEXT: [[SEQUENCE_FN:%.*]] = function_ref @$s4main8sequenceyyF // CHECK-NEXT: apply [[SEQUENCE_FN]]() // Leave the function. // CHECK-NEXT: destroy_addr [[TUPLE]] : $*(repeat each T) // CHECK-NEXT: dealloc_stack [[TUPLE]] : $*(repeat each T) // CHECK-NEXT: [[RET:%.*]] = tuple () // CHECK-NEXT: return [[RET]] : $() func callCopyAndBind(args: repeat each T) { let result = copyIntoTuple(repeat each args) sequence() } struct Wrapper { let value: Value } // CHECK-LABEL: @$s4main17wrapTupleElementsyAA7WrapperVyxGxQp_txxQpRvzlF // CHECK-SAME: $@convention(thin) (@pack_guaranteed Pack{repeat each T}) -> @pack_out Pack{repeat Wrapper} func wrapTupleElements(_ value: repeat each T) -> (repeat Wrapper) { // CHECK: [[VALUES:%.*]] = alloc_stack [lexical] [var_decl] $(repeat Wrapper), let, // CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0 // CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1 // CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T} // CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word) // CHECK: bb1([[IDX:%.*]] : $Builtin.Word) // CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1 // CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb3, bb2 // CHECK: bb2: // CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat Wrapper} // CHECK-NEXT: open_pack_element [[INDEX]] of at , shape $each T, uuid [[UUID:".*"]] // CHECK-NEXT: [[ELT_ADDR:%.*]] = tuple_pack_element_addr [[INDEX]] of [[VALUES]] : $*(repeat Wrapper) as $*Wrapper<@pack_element([[UUID]]) each T> // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Wrapper<@pack_element([[UUID]]) each T>.Type // CHECK-NEXT: [[ARG_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %1 : $*Pack{repeat each T} as $*@pack_element([[UUID]]) each T // CHECK-NEXT: [[ARG_COPY:%.*]] = alloc_stack $@pack_element([[UUID]]) each T // CHECK-NEXT: copy_addr [[ARG_ELT_ADDR]] to [init] [[ARG_COPY]] : $*@pack_element([[UUID]]) each T // CHECK-NEXT: // function_ref // CHECK-NEXT: [[INIT:%.*]] = function_ref @$s4main7WrapperV5valueACyxGx_tcfC : $@convention(method) <τ_0_0> (@in τ_0_0, @thin Wrapper<τ_0_0>.Type) -> @out Wrapper<τ_0_0> // CHECK-NEXT: apply [[INIT]]<@pack_element([[UUID]]) each T>([[ELT_ADDR]], [[ARG_COPY]], [[METATYPE]]) // CHECK-NEXT: dealloc_stack [[ARG_COPY]] // CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word // CHECK-NEXT: br bb1([[NEXT_IDX]] : $Builtin.Word) // CHECK: bb3: let values = (repeat Wrapper(value: each value)) // CHECK-NEXT: [[VALUES_COPY:%.*]] = alloc_stack $(repeat Wrapper) // CHECK-NEXT: copy_addr [[VALUES]] to [init] [[VALUES_COPY]] : $*(repeat Wrapper) // CHECK-NEXT: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0 // CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1 // CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each T} // CHECK-NEXT: br bb4([[ZERO]] : $Builtin.Word) // CHECK: bb4([[IDX:%.*]] : $Builtin.Word) // CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1 // CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb6, bb5 // CHECK: bb5: // CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat Wrapper} // CHECK-NEXT: open_pack_element [[INDEX]] of at , shape $each T, uuid [[UUID:".*"]] // CHECK-NEXT: [[OUT_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %0 : $*Pack{repeat Wrapper} as $*Wrapper<@pack_element([[UUID]]) each T> // CHECK-NEXT: [[VALUES_COPY_ELT_ADDR:%.*]] = tuple_pack_element_addr [[INDEX]] of [[VALUES_COPY]] : $*(repeat Wrapper) as $*Wrapper<@pack_element([[UUID]]) each T> // CHECK-NEXT: copy_addr [take] [[VALUES_COPY_ELT_ADDR]] to [init] [[OUT_ELT_ADDR]] : $*Wrapper<@pack_element([[UUID]]) each T> // CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word // CHECK-NEXT: br bb4([[NEXT_IDX]] : $Builtin.Word) // CHECK: bb6: // CHECK-NEXT: dealloc_stack [[VALUES_COPY]] : // CHECK-NEXT: destroy_addr [[VALUES]] : // CHECK-NEXT: dealloc_stack [[VALUES]] : // CHECK-NEXT: [[RET:%.*]] = tuple () // CHECK-NEXT: return [[RET]] : $() return values } struct Pair { init(_ first: First, _ second: Second) {} } // CHECK-LABEL: @$s4main9makePairs6firsts7secondsAA4PairVyxq_GxQp_txxQp_q_xQptRvzRv_q_Rhzr0_lF // CHECK-SAME: $@convention(thin) (@pack_guaranteed Pack{repeat each First}, @pack_guaranteed Pack{repeat each Second}) -> @pack_out Pack{repeat Pair} func makePairs( firsts first: repeat each First, seconds second: repeat each Second ) -> (repeat Pair) { // CHECK: [[ZERO:%.*]] = integer_literal $Builtin.Word, 0 // CHECK-NEXT: [[ONE:%.*]] = integer_literal $Builtin.Word, 1 // CHECK-NEXT: [[LEN:%.*]] = pack_length $Pack{repeat each First} // CHECK-NEXT: br bb1([[ZERO]] : $Builtin.Word) // CHECK: bb1([[IDX:%.*]] : $Builtin.Word) // CHECK-NEXT: [[IDX_EQ_LEN:%.*]] = builtin "cmp_eq_Word"([[IDX]] : $Builtin.Word, [[LEN]] : $Builtin.Word) : $Builtin.Int1 // CHECK-NEXT: cond_br [[IDX_EQ_LEN]], bb3, bb2 // CHECK: bb2: // CHECK-NEXT: [[INDEX:%.*]] = dynamic_pack_index [[IDX]] of $Pack{repeat Pair} // CHECK-NEXT: open_pack_element [[INDEX]] of at , shape $each First, uuid [[UUID:".*"]] // CHECK-NEXT: [[OUT_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %0 : $*Pack{repeat Pair} as $*Pair<@pack_element([[UUID]]) each First, @pack_element([[UUID]]) each Second> // CHECK-NEXT: [[METATYPE:%.*]] = metatype $@thin Pair<@pack_element([[UUID]]) each First, @pack_element([[UUID]]) each Second>.Type // CHECK-NEXT: [[FIRST_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %1 : $*Pack{repeat each First} as $*@pack_element([[UUID]]) each First // CHECK-NEXT: [[FIRST_COPY:%.*]] = alloc_stack $@pack_element([[UUID]]) each First // CHECK-NEXT: copy_addr [[FIRST_ELT_ADDR]] to [init] [[FIRST_COPY]] : $*@pack_element([[UUID]]) each First // CHECK-NEXT: [[SECOND_ELT_ADDR:%.*]] = pack_element_get [[INDEX]] of %2 : $*Pack{repeat each Second} as $*@pack_element([[UUID]]) each Second // CHECK-NEXT: [[SECOND_COPY:%.*]] = alloc_stack $@pack_element([[UUID]]) each Second // CHECK-NEXT: copy_addr [[SECOND_ELT_ADDR]] to [init] [[SECOND_COPY]] : $*@pack_element([[UUID]]) each Second // CHECK-NEXT: // function_ref // CHECK-NEXT: [[FN:%.*]] = function_ref // CHECK-NEXT: [[PAIR:%.*]] = apply [[FN]]<@pack_element([[UUID]]) each First, @pack_element([[UUID]]) each Second>([[FIRST_COPY]], [[SECOND_COPY]], [[METATYPE]]) // CHECK-NEXT: dealloc_stack [[SECOND_COPY]] : $*@pack_element([[UUID]]) each Second // CHECK-NEXT: dealloc_stack [[FIRST_COPY]] : $*@pack_element([[UUID]]) each First // CHECK-NEXT: store [[PAIR]] to [trivial] [[OUT_ELT_ADDR]] : $*Pair<@pack_element([[UUID]]) each First, @pack_element([[UUID]]) each Second> // CHECK-NEXT: [[NEXT_IDX:%.*]] = builtin "add_Word"([[IDX]] : $Builtin.Word, [[ONE]] : $Builtin.Word) : $Builtin.Word // CHECK-NEXT: br bb1([[NEXT_IDX]] : $Builtin.Word) // CHECK: bb3: // CHECK-NEXT: [[RET:%.*]] = tuple () // CHECK-NEXT: return [[RET]] : $() return (repeat Pair(each first, each second)) } protocol Container { associatedtype Contents var contents: Contents { get } } func makeContentsPairs( firsts first: repeat each First, seconds second: repeat each Second ) -> (repeat Pair<(each First).Contents, (each Second).Contents>) { return (repeat Pair((each first).contents, (each second).contents)) }