mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
LLD relocates some of the metadata sections resulting in bad offsets at runtime. The workaround is to pass `-no-rosegment` to the linker invocation. rdar://159139154
326 lines
14 KiB
Plaintext
326 lines
14 KiB
Plaintext
|
|
// REQUIRES: no_asan
|
|
|
|
// https://github.com/apple/swift/issues/55339
|
|
// XFAIL: OS=openbsd
|
|
// UNSUPPORTED: OS=linux-android, OS=linux-androideabi
|
|
|
|
// RUN: %empty-directory(%t)
|
|
// RUN: %target-build-swift %s -emit-module -emit-library -module-name capture_descriptors -o %t/capture_descriptors%{target-shared-library-suffix} -L%t/../../.. -lBlocksRuntime
|
|
// RUN: %target-swift-reflection-dump %t/capture_descriptors%{target-shared-library-suffix} | %FileCheck %s
|
|
|
|
// lld on FreeBSD relocates some of the metadata sections resulting in invalid
|
|
// offsets in section headers, breaking the Swift reflection data ELF parser
|
|
// resulting in missing metadata.
|
|
// rdar://159139154
|
|
// XFAIL: OS=freebsd
|
|
|
|
sil_stage canonical
|
|
|
|
import Builtin
|
|
import Swift
|
|
import SwiftShims
|
|
|
|
// CHECK: CAPTURE DESCRIPTORS:
|
|
// CHECK-NEXT: ====================
|
|
|
|
// Concrete caller and callee -- nothing interesting going on
|
|
|
|
protocol P {}
|
|
extension Int: P {}
|
|
|
|
sil [ossa] @concrete_callee1 : $@convention(thin) (Int, @owned <τ_0_0> { var τ_0_0 } <Int>, @thin Int.Type, @thick P.Type) -> () {
|
|
bb0(%i : $Int, %b : @owned $<τ_0_0> { var τ_0_0 } <Int>, %m : $@thin Int.Type, %p : $@thick P.Type):
|
|
%12 = tuple ()
|
|
destroy_value %b : $<τ_0_0> { var τ_0_0 } <Int>
|
|
return %12 : $()
|
|
}
|
|
|
|
sil [ossa] @concrete_caller1 : $@convention(thin) (Int, @thick P.Type) -> @owned @callee_guaranteed () -> () {
|
|
bb0(%i : $Int, %p : $@thick P.Type):
|
|
%f = function_ref @concrete_callee1 : $@convention(thin) (Int, @owned <τ_0_0> { var τ_0_0 } <Int>, @thin Int.Type, @thick P.Type) -> ()
|
|
%b = alloc_box $<τ_0_0> { var τ_0_0 } <Int>
|
|
%m = metatype $@thin Int.Type
|
|
%c = partial_apply [callee_guaranteed] %f(%i, %b, %m, %p) : $@convention(thin) (Int, @owned <τ_0_0> { var τ_0_0 } <Int>, @thin Int.Type, @thick P.Type) -> ()
|
|
return %c : $@callee_guaranteed () -> ()
|
|
}
|
|
|
|
// This is the descriptor for '<τ_0_0> { var τ_0_0 } <Int>' above
|
|
|
|
// CHECK: - Capture types:
|
|
// CHECK-NEXT: (struct Swift.Int)
|
|
// CHECK-NEXT: - Metadata sources:
|
|
|
|
// CHECK: - Capture types:
|
|
// CHECK-NEXT: (struct Swift.Int)
|
|
// CHECK-NEXT: (sil_box_with_layout
|
|
// CHECK-NEXT: (layout
|
|
// CHECK-NEXT: (var
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=0)))
|
|
// CHECK-NEXT: (generic_signature
|
|
// CHECK-NEXT: (substitution
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=0)
|
|
// CHECK-NEXT: (struct Swift.Int))))
|
|
// CHECK-NEXT: (existential_metatype
|
|
// CHECK-NEXT: (protocol_composition
|
|
// CHECK-NEXT: (protocol capture_descriptors.P)))
|
|
// CHECK-NEXT: - Metadata sources:
|
|
|
|
|
|
// Concrete caller and generic callee -- capture types are fully substituted,
|
|
// and there are no metadata bindings
|
|
|
|
sil [ossa] @generic_callee2 : $@convention(thin) <T, U> (@in T, @owned <τ_0_0> { var τ_0_0 } <U>) -> () {
|
|
bb0(%i : $*T, %b : @owned $<τ_0_0> { var τ_0_0 } <U>):
|
|
%12 = tuple ()
|
|
destroy_value %b : $<τ_0_0> { var τ_0_0 } <U>
|
|
destroy_addr %i : $*T
|
|
return %12 : $()
|
|
}
|
|
|
|
sil [ossa] @concrete_caller2 : $@convention(thin) (Int) -> @owned @callee_guaranteed () -> () {
|
|
bb0(%0 : $Int):
|
|
%f = function_ref @generic_callee2 : $@convention(thin) <T, U> (@in T, @owned <τ_0_0> { var τ_0_0 } <U>) -> ()
|
|
%i = alloc_stack $Int
|
|
store %0 to [trivial] %i : $*Int
|
|
%b = alloc_box $<τ_0_0> { var τ_0_0 } <String>
|
|
%c = partial_apply [callee_guaranteed] %f<Int, String>(%i, %b) : $@convention(thin) <T, U> (@in T, @owned <τ_0_0> { var τ_0_0 } <U>) -> ()
|
|
dealloc_stack %i : $*Int
|
|
return %c : $@callee_guaranteed () -> ()
|
|
}
|
|
|
|
// This is the descriptor for '<τ_0_0> { var τ_0_0 } <String>' above
|
|
|
|
// CHECK: - Capture types:
|
|
// CHECK-NEXT: (struct Swift.String)
|
|
// CHECK-NEXT: - Metadata sources:
|
|
|
|
// CHECK: - Capture types:
|
|
// CHECK-NEXT: (struct Swift.Int)
|
|
// CHECK-NEXT: (sil_box_with_layout
|
|
// CHECK-NEXT: (layout
|
|
// CHECK-NEXT: (var
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=0)))
|
|
// CHECK-NEXT: (generic_signature
|
|
// CHECK-NEXT: (substitution
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=0)
|
|
// CHECK-NEXT: (struct Swift.String))))
|
|
// CHECK-NEXT: - Metadata sources:
|
|
|
|
|
|
// Generic caller and generic callee -- capture types are written in terms of
|
|
// the caller's generic parameters, and metadata bindings are present for
|
|
// structural sub-terms of the callee's substituted generic parameters that
|
|
// contain the caller's generic parameters.
|
|
|
|
sil [ossa] @generic_callee3 : $@convention(thin) <T, U> (@in_guaranteed T) -> () {
|
|
bb0(%t : $*T):
|
|
%12 = tuple ()
|
|
return %12 : $()
|
|
}
|
|
|
|
sil [ossa] @generic_caller3 : $@convention(thin) <A, B, C> (@owned Optional<@callee_guaranteed @substituted <X, Y> (@in_guaranteed X) -> @out Y for <A, B>>) -> @owned @callee_guaranteed () -> () {
|
|
bb0(%0 : @owned $Optional<@callee_guaranteed @substituted <X, Y> (@in_guaranteed X) -> @out Y for <A, B>>):
|
|
%f = function_ref @generic_callee3 : $@convention(thin) <T, U> (@in_guaranteed T) -> ()
|
|
%t = alloc_stack $Optional<@callee_guaranteed @substituted <X, Y> (@in_guaranteed X) -> @out Y for <A, B>>
|
|
store %0 to [init] %t : $*Optional<@callee_guaranteed @substituted <X, Y> (@in_guaranteed X) -> @out Y for <A, B>>
|
|
%c = partial_apply [callee_guaranteed] %f<Optional<(A) -> B>, (B, (C) -> Int)>(%t) : $@convention(thin) <T, U> (@in_guaranteed T) -> ()
|
|
dealloc_stack %t : $*Optional<@callee_guaranteed @substituted <X, Y> (@in_guaranteed X) -> @out Y for <A, B>>
|
|
return %c : $@callee_guaranteed () -> ()
|
|
}
|
|
|
|
// CHECK: - Capture types:
|
|
// CHECK-NEXT: (bound_generic_enum Swift.Optional
|
|
// CHECK-NEXT: (function
|
|
// CHECK-NEXT: (parameters)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (tuple)))
|
|
// CHECK-NEXT: - Metadata sources:
|
|
// CHECK-NEXT: (bound_generic_enum Swift.Optional
|
|
// CHECK-NEXT: (function
|
|
// CHECK-NEXT: (parameters
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=0)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=1)))
|
|
// CHECK-NEXT: (closure_binding index=0)
|
|
// CHECK-NEXT: (tuple
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
|
|
// CHECK-NEXT: (function
|
|
// CHECK-NEXT: (parameters
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=2)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (struct Swift.Int)))
|
|
// CHECK-NEXT: (closure_binding index=1)
|
|
|
|
|
|
// Generic caller and generic callee -- and one of the type parameters is
|
|
// fulfilled by a thick metatype value.
|
|
|
|
sil [ossa] @generic_callee4 : $@convention(thin) <T, U> (@thick Optional<T>.Type) -> () {
|
|
bb0(%t : $@thick Optional<T>.Type):
|
|
%12 = tuple ()
|
|
return %12 : $()
|
|
}
|
|
|
|
sil [ossa] @generic_caller4 : $@convention(thin) <A, B, C> () -> @owned @callee_guaranteed () -> () {
|
|
bb0:
|
|
%f = function_ref @generic_callee4 : $@convention(thin) <T, U> (@thick Optional<T>.Type) -> ()
|
|
%t = metatype $@thick Optional<(B) -> C>.Type
|
|
%c = partial_apply [callee_guaranteed] %f<(B) -> C, Int>(%t) : $@convention(thin) <T, U> (@thick Optional<T>.Type) -> ()
|
|
return %c : $@callee_guaranteed () -> ()
|
|
}
|
|
|
|
// CHECK: - Capture types:
|
|
// CHECK-NEXT: (metatype was_abstract
|
|
// CHECK-NEXT: (bound_generic_enum Swift.Optional
|
|
// CHECK-NEXT: (function
|
|
// CHECK-NEXT: (parameters
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=2))))
|
|
// CHECK-NEXT: - Metadata sources:
|
|
// CHECK-NEXT: (function
|
|
// CHECK-NEXT: (parameters
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=2))
|
|
// CHECK-NEXT: (generic_argument index=0
|
|
// CHECK-NEXT: (metadata_capture index=0))
|
|
|
|
|
|
// Generic caller and generic callee -- and one of the type parameters is
|
|
// fulfilled by the isa pointer of a class instance.
|
|
|
|
class GenericClass<T, U> {}
|
|
|
|
sil [ossa] @generic_callee5 : $@convention(thin) <T, U, V> (@owned GenericClass<T, U>) -> () {
|
|
bb0(%t : @owned $GenericClass<T, U>):
|
|
%12 = tuple ()
|
|
destroy_value %t : $GenericClass<T, U>
|
|
return %12 : $()
|
|
}
|
|
|
|
sil [ossa] @generic_caller5 : $@convention(thin) <A, B, C> (@owned GenericClass<(A, B), (B, C)>) -> @owned @callee_guaranteed () -> () {
|
|
bb0(%g : @owned $GenericClass<(A, B), (B, C)>):
|
|
%f = function_ref @generic_callee5 : $@convention(thin) <T, U, V> (@owned GenericClass<T, U>) -> ()
|
|
%c = partial_apply [callee_guaranteed] %f<(A, B), (B, C), (C, A)>(%g) : $@convention(thin) <T, U, V> (@owned GenericClass<T, U>) -> ()
|
|
return %c : $@callee_guaranteed () -> ()
|
|
}
|
|
|
|
sil_vtable GenericClass {}
|
|
|
|
// CHECK: - Capture types:
|
|
// CHECK-NEXT: (bound_generic_class capture_descriptors.GenericClass
|
|
// CHECK-NEXT: (tuple
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=0)
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=1))
|
|
// CHECK-NEXT: (tuple
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=2)))
|
|
// CHECK-NEXT: - Metadata sources:
|
|
// CHECK-NEXT: (tuple
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=2)
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=0))
|
|
// CHECK-NEXT: (closure_binding index=0)
|
|
// CHECK-NEXT: (tuple
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=0)
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=1))
|
|
// CHECK-NEXT: (generic_argument index=0
|
|
// CHECK-NEXT: (reference_capture index=0))
|
|
// CHECK-NEXT: (tuple
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=1)
|
|
// CHECK-NEXT: (generic_type_parameter depth=0 index=2))
|
|
// CHECK-NEXT: (generic_argument index=1
|
|
// CHECK-NEXT: (reference_capture index=0))
|
|
|
|
|
|
// Pseudogeneric caller and pseudogeneric callee -- type parameters are
|
|
// erased at runtime.
|
|
|
|
sil [ossa] @pseudogeneric_callee : $@convention(thin) @pseudogeneric <T : AnyObject, U : AnyObject> (@owned T, @owned U) -> () {
|
|
bb0(%t : @owned $T, %u : @owned $U):
|
|
%12 = tuple ()
|
|
destroy_value %t : $T
|
|
destroy_value %u : $U
|
|
return %12 : $()
|
|
}
|
|
|
|
sil [ossa] @pseudogeneric_caller : $@convention(thin) @pseudogeneric <A : AnyObject, B : AnyObject, C : AnyObject> (@owned A, @owned B) -> @owned @callee_guaranteed () -> () {
|
|
bb0(%a : @owned $A, %b : @owned $B):
|
|
%f = function_ref @pseudogeneric_callee : $@convention(thin) @pseudogeneric <T : AnyObject, U : AnyObject> (@owned T, @owned U) -> ()
|
|
%c = partial_apply [callee_guaranteed] %f<A, B>(%a, %b) : $@convention(thin) @pseudogeneric <A : AnyObject, B : AnyObject> (@owned A, @owned B) -> ()
|
|
return %c : $@callee_guaranteed () -> ()
|
|
}
|
|
|
|
// CHECK: - Capture types:
|
|
// CHECK-NEXT: (protocol_composition any_object)
|
|
// CHECK-NEXT: (protocol_composition any_object)
|
|
// CHECK-NEXT: - Metadata sources:
|
|
|
|
|
|
// Capturing lowered function types
|
|
|
|
sil [ossa] @function_callee : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method: P) (Int) -> ()) -> () {
|
|
bb0(%thin : $@convention(thin) () -> (), %c : $@convention(c) () -> (), %block : @unowned $@convention(block) () -> (), %thick : @unowned $@convention(thick) () -> (), %method : $@convention(method) () -> (), %witness_method : $@convention(witness_method: P) (Int) -> ()):
|
|
%12 = tuple ()
|
|
return %12 : $()
|
|
}
|
|
|
|
sil [ossa] @function_caller : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @owned @convention(block) () -> (), @owned @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method: P) (Int) -> ()) -> @owned @callee_guaranteed () -> () {
|
|
bb0(%thin: $@convention(thin) () -> (), %c: $@convention(c) () -> (), %block: @owned $@convention(block) () -> (), %thick: @owned $@convention(thick) () -> (), %method: $@convention(method) () -> (), %witness_method: $@convention(witness_method: P) (Int) -> ()):
|
|
%f = function_ref @function_callee : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method: P) (Int) -> ()) -> ()
|
|
%result = partial_apply [callee_guaranteed] %f(%thin, %c, %block, %thick, %method, %witness_method) : $@convention(thin) (@convention(thin) () -> (), @convention(c) () -> (), @convention(block) () -> (), @convention(thick) () -> (), @convention(method) () -> (), @convention(witness_method: P) (Int) -> ()) -> ()
|
|
return %result : $@callee_guaranteed () -> ()
|
|
}
|
|
|
|
// CHECK: - Capture types:
|
|
// CHECK-NEXT: (function convention=thin
|
|
// CHECK-NEXT: (parameters)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (tuple))
|
|
// CHECK-NEXT: (function convention=c
|
|
// CHECK-NEXT: (parameters)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (tuple))
|
|
// CHECK-NEXT: (function convention=block
|
|
// CHECK-NEXT: (parameters)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (tuple))
|
|
// CHECK-NEXT: (function
|
|
// CHECK-NEXT: (parameters)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (tuple))
|
|
// CHECK-NEXT: (function convention=thin
|
|
// CHECK-NEXT: (parameters)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (tuple))
|
|
// CHECK-NEXT: (function convention=thin
|
|
// CHECK-NEXT: (parameters)
|
|
// CHECK-NEXT: (result
|
|
// CHECK-NEXT: (tuple))
|
|
// CHECK-NEXT: - Metadata sources:
|
|
|
|
// Capturing opened existentials
|
|
//
|
|
// Not supported yet -- make sure we bail out instead of crashing.
|
|
//
|
|
// FIXME: Eventually, we should emit a useful capture descriptor
|
|
// for this case.
|
|
|
|
sil [ossa] @existential_callee : $@convention(thin) <τ_0_0 where τ_0_0 : P> () -> @out P {
|
|
bb0(%0 : $*P):
|
|
unreachable
|
|
}
|
|
|
|
|
|
sil [ossa] @existential_caller : $@convention(thin) (@in P) -> () {
|
|
bb0(%0 : $*P):
|
|
%payload = open_existential_addr immutable_access %0 : $*P to $*@opened("2D7A8F84-2973-11E7-838D-34363BD08DA0", P) Self
|
|
%f = function_ref @existential_callee : $@convention(thin) <τ_0_0 where τ_0_0 : P> () -> @out P
|
|
%result = partial_apply [callee_guaranteed] %f<@opened("2D7A8F84-2973-11E7-838D-34363BD08DA0", P) Self>() : $@convention(thin) <τ_0_0 where τ_0_0 : P> () -> @out P
|
|
destroy_value %result : $@callee_guaranteed () -> @out P
|
|
destroy_addr %0 : $*P
|
|
%tuple = tuple ()
|
|
return %tuple : $()
|
|
}
|