This allows us to freely pass the address of a variable of such
types to a C function without worrying about it overwriting other
things if e.g. it memcpy's sizeof(T) bytes and thus clobbers the
otherwise-non-existent tail padding.
There are ways to get this optimization back, but they require
things like materializing to a temporary instead of passing the
address directly. We haven't done that work yet, so we don't
get to take advantage of it.
rdar://26828018
Instead of hooking into nominal type and extension emission
and walking all conformances of those declarations, let's
just directly hook into the logic for emitting conformances.
This fixes an issue where we would apparently emit duplicate
conformances, as well as unnecessary conformances that are
defined elsewhere.
Rather than collection nominal type and extension decls and emit
reflection metadata records in one go, we can emit them as they
are encountered and instead collection builtin types referenced
by those at the end.
specialization to be separately lowered in IRGen, use the mangling
of the specialized type as the name of the llvm::StructType instead
of the base, unspecialized type.
This tends to produce fewer collisions between IR type names.
LLVM does unique the names on its own, so that's not strictly
necessary, but it's still a good idea because it makes the test
output more reliable and somewhat easier to read (modulo the
impact of bigger type names). Collisions will still occur if
the type is specialized at an archetype, since in this case we
will fall back on the unspecialized type.
- Implement emission of type references for nominal type field
reflection, using a small custom encoder resulting in packed
structs, not strings. This will let us embed 7-bit encoded
32-bit relative offsets directly in the structure (not yet
hooked in).
- Use the AST Mangler for encoding type references
Archetypes and internal references were complicating this before, so we
can take the opportunity to reuse this machinery and avoid unique code
and new ABI.
Next up: Tests for reading the reflection sections and converting the
demangle tree into a tree of type references.
Todo: For concrete types, serialize the types for associated types of
their conformances to bootstrap the typeref substitution process.
rdar://problem/15617914
In a few places, we have to be careful about the distinction between
"empty in this resilience domain" versus "empty in all resilience
domains". Make callers think about this by adding a parameter instead
of relying on them to check isFixedSize() as necessary first.
While making this change I noticed that the code for checking if
types are empty when computing extra inhabitants of structs and enums
might be slightly wrong in the face of resilience; I will revisit
this later.
This should cover most temporary buffers, except for those used by indirected value arguments, which need some cooperation with CallEmission to properly mark lifetime end after the call's completed.
For example, if a @_fixed_layout struct A contains a resilient struct B
from the same module M, then inside M, A can have a fixed size, but
outside, A has a dynamic size because B is opaque. In this case, A is
not "universally fixed-size". This impacts multi-payload enums, because
if A is placed inside a multi-payload enum E which is lowered inside X,
we would get a fixed layout with spare bits, but lowering E outside of
X would yield a dynamic layout. This is incorrect.
Fix this by plumbing through a new predicate IsAlwaysFixedSize, which
is similar to IsPOD and IsBitwiseTakable, where a compound type inherits
the property if all leaf types exhibit it, and only use spare bits if
the original and substituted types have this property.
If a struct has fixed layout but contains fields which are opaque,
or if the struct itself is opaque, use a metadata accessor function
instead of loading the metadata directly.
Let's say that A and B are two structs defined in the same module,
and B has a fixed size. This patch adds support for these two cases:
1) Fixed-layout struct A contains resilient struct B
2) Resilient struct A contains resilient struct B
In case 1),
a) Inside X: A is fixed-size and has constant metadata
i) Direct metadata access can be performed on A and B
ii) Direct field access can be performed on A and B
d) Outside X: B has an opaque layout
i) Metadata accessor must be called for A and B
ii) Fields of A do not have constant offsets, instead the offsets
must be loaded from type metadata
Case 2) is the same as above except ii) does not apply, since fields
of resilient structs are manipulated via accessors.
Eventually, we will use metadata accessor functions for all public
struct and enum types.
John and I discussed this and agreed that we only need two cases here,
not four. In the future this may be merged with ResilienceExpansion,
and become a struct with additional availability information, but
we're definitely sure we don't need four levels here.
Add a new ResilientStructTypeInfo. This is a singleton since
all resilient structs have opaque payloads and are accessed
through value witness tables.
With this in place, flesh out IRGenModule::isResilient() and
use the new singleton to convert resilient structs.
Note that the old isResilient() was hard-coded to report that
all Clang-imported classes are "resilient". Now that this has
been unified with NominalTypeDecl::hasFixedLayout(), we will
report Clang-imported classes are "resilient" at the SIL level.
This should not introduce any semantic differences at this
point.
Unlike SIL, where currently resilient types are always resilient
even when used from the same module, IRGen is able to perform
direct manipulation of resilient structs from the current
module, since IRGen's type lowering has a resilience scope
plumbed through.
Note that we do not yet support laying out structs and classes
containing resilient fields -- this will come in a future patch.
Bitfields are imported as computed properties with Clang-generated
accessors.
While we cannot represent them directly in SIL, we can still
synthesize a memberwise initializer, so also decouple that notion
from "has unreferenceable storage".
Fixes <rdar://problem/21702107>.
Swift SVN r31779
Full type metadata isn't necessary to calculate the runtime layout of a dependent struct or enum; we only need the non-function data from the value witness table (size, alignment, extra inhabitant count, and POD/BT/etc. flags). This can be generated more efficiently than the type metadata for many types--if we know a specific instantiation is fixed-layout, we can regenerate the layout information, or if we know the type has the same layout as another well-known type, we can get the layout from a common value witness table. This breaks a deadlock in most (but not all) cases where a value type is recursive using classes or fixed-layout indirected structs like UnsafePointer. rdar://problem/19898165
This time, factor out the ObjC-dependent parts of the tests so they only run with ObjC interop.
Swift SVN r30266
Full type metadata isn't necessary to calculate the runtime layout of a dependent struct or enum; we only need the non-function data from the value witness table (size, alignment, extra inhabitant count, and POD/BT/etc. flags). This can be generated more efficiently than the type metadata for many types--if we know a specific instantiation is fixed-layout, we can regenerate the layout information, or if we know the type has the same layout as another well-known type, we can get the layout from a common value witness table. This breaks a deadlock in most (but not all) cases where a value type is recursive using classes or fixed-layout indirected structs like UnsafePointer. rdar://problem/19898165
Swift SVN r30243
Using LLVM large integers to represent enum payloads has been causing compiler performance and code size problems with large types, and has also exposed a long tail of backend bugs. Replace them with an "EnumPayload" abstraction that manages breaking a large opaque binary value into chunks, along with masking, testing, and extracting typed data from the binary blob. For now, use a word-sized chunking schema always, though the architecture here is set up to eventually allow the use of an arbitrary explosion schema, which would benefit single-payload enums by allowing the payload to follow the explosion schema of the contained value.
This time, adjust the assertion in emitCompare not to perform a check before we've established that the payload is empty, since APInt doesn't have a 0-bit state and the default-constructed form is nondeterminisitic. (We should probably use a more-tailored representation for enum payload bit patterns than APInt or ClusteredBitVector.)
Swift SVN r28985
Using LLVM large integers to represent enum payloads has been causing compiler performance and code size problems with large types, and has also exposed a long tail of backend bugs. Replace them with an "EnumPayload" abstraction that manages breaking a large opaque binary value into chunks, along with masking, testing, and extracting typed data from the binary blob. For now, use a word-sized chunking schema always, though the architecture here is set up to eventually allow the use of an arbitrary explosion schema, which would benefit single-payload enums by allowing the payload to follow the explosion schema of the contained value.
Swift SVN r28982
This is an internal-only affordance for the numerics team to be able to work on SIMD-compatible types. For now, it can only increase alignment of fixed-layout structs and enums; dynamic layout, classes, and other obvious extensions are left to another day when we can design a proper layout control design.
Swift SVN r27323
Sometimes these methods are overriding, sometimes they're not.
Unfortunately, there's not a very consistent solution, so just disable
the warning in these two .cpp files.
No functionality change.
Swift SVN r25604
Per the previous commit we are no longer using this. Minor save in
simplicity and maybe a bit of compilation time as well.
In the long run IRGen probably shouldn't be pulling information from the
AST at all; the SILModule should be able to tell it what types it needs
to emit information for. But this is still an improvement for now.
No functionality change (that was the previous commit).
Swift SVN r24840
IRGen uses a typedef, SpareBitVector, for its principal
purpose of tracking spare bits. Other uses should not
use this typedef, and I've tried to follow that, but I
did this rewrite mostly with sed and may have missed
some fixups.
This should be almost completely NFC. There may be
some subtle changes in spare bits for witness tables
and other off-beat pointer types. I also fixed a bug
where IRGen thought that thin functions were two
pointers wide, but this wouldn't have affected anything
because we never store thin functions anyway, since
they're not a valid AST type.
This commit repplies r24305 with two fixes:
- It fixes the computation of spare bits for unusual
integer types to use the already-agreed-upon type
size instead of recomputing it. This fixes the
i386 stdlib build. Joe and I agreed that we should
also change the size to use the LLVM alloc size
instead of the next power of 2, but this patch
does not do that yet.
- It changes the spare bits in function types back
to the empty set. I'll be changing this in a
follow-up, but it needs to be tied to runtime
changes. This fixes the regression test failures.
Swift SVN r24324
IRGen uses a typedef, SpareBitVector, for its principal
purpose of tracking spare bits. Other uses should not
use this typedef, and I've tried to follow that, but I
did this rewrite mostly with sed and may have missed
some fixups.
This should be almost completely NFC. There may be
some subtle changes in spare bits for witness tables
and other off-beat pointer types. I also fixed a bug
where IRGen thought that thin functions were two
pointers wide, but this wouldn't have affected anything
because we never store thin functions anyway, since
they're not a valid AST type.
Swift SVN r24305
llvm::Optional lives in "llvm/ADT/Optional.h". Like Clang, we can get
Optional in the 'swift' namespace by including "swift/Basic/LLVM.h".
We're now fully switched over to llvm::Optional!
Swift SVN r22477
- A spot fix in SILGen for reabstracting the result of a downcast, which fixes checked casts to function types.
- Associate the layout information in type metadata records with the most abstract representation of the type. This is the correct thing to do in cases where we need the metadata as a tag for an opaque value--if we store a value in an Any, or pass it as an unconstrained generic parameter, we must maximally reabstract it. This fixes the value semantics of existentials containing trivial metatypes.
- To ensure that we get runtime layout of structs and enums correct when they contain reabstractable types, introduce a "metadata for layout" concept, which doesn't need to describe the canonical metadata for the type, but only needs to describe a type with equivalent layout and value semantics. This is a correctness fix that allows us to correctly lay out generic types containing dependent tuples and functions, and although we don't really take advantage of it here, it's also a potential runtime performance win down the road, because we could potentially produce direct metadata for a primitive type that's layout-equivalent with a runtime-instantiated type. To aid in type safety here, push SILType deeper into IRGen in places where we potentially care about specific representations of types.
- Finally, fix an inconsistency between the runtime and IRGen's concept of what spare bits unmanaged references and thick metatypes have.
Together, these fixes address rdar://problem/16406907, rdar://problem/17822208, rdar://problem/18189508, and likely many other related issues, and also fixes crash suite cases 012 and 024.
Swift SVN r21963
Specifically, it should not ever have a clang::TypedefDecl as its Clang node,
even if the RecordDecl is anonymous and immediately wrapped in a typedef.
It looks like no one was ever doing this intentionally; it's just left over
from before we looked through typedefs at all. This is important because we
use the clang::RecordDecl for IRGen layout if it's present; before this patch
we would fall back to Swift layout for these structs (clearly wrong).
The one exception here is enums -- NS_OPTIONS and named C enums get imported
as structs as well. If we add any other exceptions, we should be sure they
are dealt with in IRGen as well.
The change in the printed interface output is due to the source location
for the Clang node of an NS_ENUM or NS_OPTIONS decl being inside a macro.
I didn't see a quick fix for this, so I'm going to ignore it for now.
Swift SVN r21748
If a type has to be passed or returned resiliently, it
will necessarily be passed indirectly, which is already
represented in SILFunctionType. There is no need to
represent this as a separate channel of information.
NFC. Also fixes a problem where the signature cache
for ExtraData::Block was writing past the end of an
array (but into the storage for an adjacent array
which was fortunately never used).
ExtraData should also disappear as a concept, but we're
still relying on that for existential protocol witnesses.
Swift SVN r21548
LLDB needs this in order to accurately test enums that use extra inhabitants of aggregates, for which we don't guarantee that we set all of the bits to an exact value. Allows lldb to address <rdar://problem/17787682>. Now with no test crashes.
Swift SVN r20545
LLDB needs this in order to accurately test enums that use extra inhabitants of aggregates, for which we don't guarantee that we set all of the bits to an exact value. Allows lldb to address <rdar://problem/17787682>.
Swift SVN r20527
for extra inhabitants.
For structs in particular, this eliminates a major source
of abstraction penatlies. For example, an optional struct
containing an object pointer is now represented the same
way as an optional object pointer, which is critical for
correctly importing CF types as Unmanaged<T>!.
In time, we should generalize this to consider all elements
as sources for extra inhabitants, as well as exploiting
spare bits in the representation, but getting the
single-element case right really provides the bulk of the
benefit.
This commit restores r17242 and r17243 with a fix to use
value witnesses that actually forward the right type metadata
down. We were already generating these value witnesses in
the dependent struct VWT pattern, but I was being too clever
and trying to use the underlying value witness directly.
Swift SVN r17267
This reverts commit r17243. We can't just forward the extra inhabitant payloads
from a field, because they will end up receiving metadata for the incorrect
type and crashing.
Swift SVN r17251
extra inhabitants.
Obviously this should eventually be generalized to
take from any element, but this is good enough to
give us zero-cost abstraction via single-field structs.
Contains some bugfixes for the tuple-extra-inhabitant
changes as well, because test coverage for optional
structs is obviously quite a bit richer than for
optional tuples.
All of this is leading towards unblocking IRGen for
importing CFStringRef as Unmanaged<CFString>!.
Swift SVN r17243