The uniquing key for these was just the number of witness tables,
but the function itself referenced the specific existential type
it was instantiated with.
Everything still worked because getOrCreateHelperFunction() would
bitcast an existing function to the correct type, and in practice
the layout of an existential type only depends on the number of
witness tables.
However on master-next, other changes were made that stripped
off the bitcasts. This would result in assertions or LLVM
verifier failures when multiple existential types were used in
a single translation unit.
Fixes <rdar://problem/54780404>.
In too many places, we were calling into `emitDynamicTypeOfOpaqueHeapObject` even when we had
more specific type information about the heap object we were querying. Replace all calls with
`emitDynamicTypeOfHeapObject`, which uses the best available access path and completely avoids
runtime calls for pure Swift classes and heap objects. When targeting non-ObjC-interop platforms,
we also know we never need to call `swift_getObjectType`, so avoid doing so altogether.
Certain uses of protocols only formally need the requirement
signature, not any of the method requirements. This results in IRGen
seeing a protocol where none of the members have been validated except
the associated types. Account for this by allowing ProtocolInfo to
only contain the layout for the base protocols and associated types,
if requested.
Note that this relies on the layout of a witness table always putting
the "requirement signature part" at the front, or at least at offsets
that aren't affected by function requirements.
rdar://problem/43260117