initialization in-place on demand. Initialize parent metadata
references correctly on struct and enum metadata.
Also includes several minor improvements related to relative
pointers that I was using before deciding to simply switch the
parent reference to an absolute reference to get better access
patterns.
Includes a fix since the earlier commit to make enum metadata
writable if they have an unfilled payload size. This didn't show
up on Darwin because "constant" is currently unenforced there in
global data containing relocations.
This patch requires an associated LLDB change which is being
submitted in parallel.
initialization in-place on demand. Initialize parent metadata
references correctly on struct and enum metadata.
Also includes several minor improvements related to relative
pointers that I was using before deciding to simply switch the
parent reference to an absolute reference to get better access
patterns.
"minimal" is defined as the set of requirements that would be
passed to a function with the type's generic signature that
takes the thick metadata of the parent type as its only argument.
Similarly to how we've always handled parameter types, we
now recursively expand tuples in result types and separately
determine a result convention for each result.
The most important code-generation change here is that
indirect results are now returned separately from each
other and from any direct results. It is generally far
better, when receiving an indirect result, to receive it
as an independent result; the caller is much more likely
to be able to directly receive the result in the address
they want to initialize, rather than having to receive it
in temporary memory and then copy parts of it into the
target.
The most important conceptual change here that clients and
producers of SIL must be aware of is the new distinction
between a SILFunctionType's *parameters* and its *argument
list*. The former is just the formal parameters, derived
purely from the parameter types of the original function;
indirect results are no longer in this list. The latter
includes the indirect result arguments; as always, all
the indirect results strictly precede the parameters.
Apply instructions and entry block arguments follow the
argument list, not the parameter list.
A relatively minor change is that there can now be multiple
direct results, each with its own result convention.
This is a minor change because I've chosen to leave
return instructions as taking a single operand and
apply instructions as producing a single result; when
the type describes multiple results, they are implicitly
bound up in a tuple. It might make sense to split these
up and allow e.g. return instructions to take a list
of operands; however, it's not clear what to do on the
caller side, and this would be a major change that can
be separated out from this already over-large patch.
Unsurprisingly, the most invasive changes here are in
SILGen; this requires substantial reworking of both call
emission and reabstraction. It also proved important
to switch several SILGen operations over to work with
RValue instead of ManagedValue, since otherwise they
would be forced to spuriously "implode" buffers.
This prevents the linker from trying to emit relative relocations to locally-defined public symbols into dynamic libraries, which gives ld.so heartache.
- 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
Decrease the size of nominal type descriptors and make them true-const by relative-addressing the other metadata they need to reference, which should all be included in the same image as the descriptor itself. Relative-referencing string constants exposes a bug in the Apple linker, which crashes when resolving relative relocations to coalesceable symbols (rdar://problem/22674524); work around this for now by revoking the `unnamed_addr`-ness of string constants that we take relative references to. (I haven't tested whether GNU ld or gold also have this problem on Linux; it may be possible to conditionalize the workaround to only apply to Darwin targets for now.)
Since that's somewhat expensive, allow the generation of meaningful
IR value names to be efficiently controlled in IRGen. By default,
enable meaningful value names only when generating .ll output.
I considered giving protocol witness tables the name T:Protocol
instead of T.Protocol, but decided that I didn't want to update that
many test cases.
Decrease the size of nominal type descriptors and make them true-const by relative-addressing the other metadata they need to reference, which should all be included in the same image as the descriptor itself. Relative-referencing string constants exposes a bug in the Apple linker, which crashes when resolving relative relocations to coalesceable symbols (rdar://problem/22674524); work around this for now by revoking the `unnamed_addr`-ness of string constants that we take relative references to. (I haven't tested whether GNU ld or gold also have this problem on Linux; it may be possible to conditionalize the workaround to only apply to Darwin targets for now.)
A single extra inhabitant is good enough for the most important case,
that being a single level of optionality. Otherwise, we want to
reserve maximal flexibility for the implementation.
This commit also fixes a bug where I was not correctly defining
the extra-inhabitant rules for all of the existential cases.
This value witness function takes an address of an enum value where the
payload has already been initialized, together with a case index, and
forms the enum value.
The formal behavior can be thought of as satisfying an identity in
relation to the existing two enum value witnesses. For any enum
value, the following is to leave the value unchanged:
tag = getEnumTag(value)
destructiveProjectEnumData(value)
destructiveInjectEnumData(value, tag)
This is the last missing piece for the inject_enum_addr SIL instruction
to handle resilient enums, allowing the implementation of an enum to be
decoupled from its uses. Also, it should be useful for dynamically
constructing enum cases with write reflection, once we get around to
doing such a thing.
The body of the value witness is emitted by a new emitStoreTag() method
on EnumImplStrategy. This is similar to the existing storeTag(), except
the case index is a value instead of a contant.
This is implemented as follows for the different enum strategies:
1) For enums consisting of a single case, this is trivial.
2) For enums where all cases are empty, stores the case index into the
payload area.
3) For enums with a single payload case, emits a call to a runtime
function. Note that for non-generic single payload enums, this could
be open-coded more efficiently, but the function still has the
correct behavior since it supports extra inhabitants and so on.
A follow-up patch will make this more efficient.
4) For multi-payload enums, there are two cases:
a) If one of the payloads is generic or resilient, the enum is
dynamically-sized, and a call to a runtime function is emitted.
b) If the entire enum is fixed-size, the value witness checks if
the case is empty or not.
If the case has a payload, the case index is swizzled into
spare bits of the payload, if any, with remaining bits going
into the extra tag area.
If the case is empty, the case index is swizzled into the
spare bits of the payload, the remaining bits of the payload,
and the extra tag area.
The implementations of emitStoreTag() duplicate existing logic in the
enum strategies, in particular case 4)b) is rather complicated.
Code cleanups are welcome here!
The previous patch added an assert, but it turns out we could still
end up in this code path if the payload was fixed-size *and*
address-only. This is not a very common case, so don't try to
optimize it.
The swift_unknown* entry points are not available on the Linux port.
Previously we would still attempt to use them in a couple of cases:
1) Foreign classes
2) Existentials and archetypes
3) Optionals of boxed existentials
Note that this patch changes IRGen to never emit the
swift_errorRelease/Retain entry points on Linux. We would like to
use them in the future if we ever adopt a tagged-pointer representation
for small errors. In this case, they can be brought back, and the
TypeInfo for optionals will need to be generalized to propagate the
reference counting of the payload type, instead of defaulting to
unknown if the payload type is not natively reference counted.
A similar change will need to be made to support blocks, if we ever
want to use the blocks runtime on Linux.
Fixes <rdar://problem/23335318>, <rdar://problem/23335537>,
<rdar://problem/23335453>.
And include some supplementary mangling changes:
- Give the first generic param (depth=0, index=0) a single character mangling. Even after removing the self type from method declaration types, 'Self' still shows up very frequently in protocol requirement signatures.
- Fix the mangling of generic parameter counts to elide the count when there's only one parameter at the starting depth of the mangling.
Together these carve another 154KB out of a debug standard library. There's some awkwardness in demangled strings that I'll clean up in subsequent commits; since decl types now only mangle the number of generic params at their own depth, it's context-dependent what depths those represent, which we get wrong now. Currying markers are also wrong, but since free function currying is going away, we can mangle the partial application thunks in different ways.
Swift SVN r32896
If we have an unowned/weak protocol type with witness tables, we can't use the prefab NativeObject/UnknownObject layouts. While we're here, fix up some tests for 32-bit portability too.
Swift SVN r30270
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
In the case where there is a single tag bit and extra inhabitants, we
generate a conditional branch, but we weren't emitting both destination
blocks.
Fixes rdar://problem/21742335.
Swift SVN r30228
These will be used for reflection, and eventually to speed up generic
operations on single payload enums as well.
Progress on <rdar://problem/21739870>.
Swift SVN r30214
This nicely gathers all the layout information together in one contiguous bundle we can potentially emit independently for use in generic type layout. A step on the way to rdar://problem/19898165.
Swift SVN r30128
These classes don't show up well in generated headers (rdar://problem/20855568),
can't actually be allocated from Objective-C (rdar://problem/17184317), and
make the story of "what is exposed to Objective-C" more complicated. Better
to just disallow them.
All classes are still "id-compatible" in that they can be converted to
AnyObject and passed to Objective-C, they secretly implement NSObjectProtocol
(via our SwiftObject root class), and their members can still be individually
exposed to Objective-C.
The frontend flag -disable-objc-attr-requires-foundation-module will disable
this requirement as well, which is still necessary for both the standard
library and a variety of tests I didn't feel like transforming.
Swift SVN r29760
@inout parameters can be nocapture and dereferenceable. @in, @in_guaranteed, and indirected @direct parameters can be noalias, nocapture, and dereferenceable.
Swift SVN r29353
If an enum has only a single tag bit, emit a cond_br instead of a switch, and if it has only one no-payload case, jump directly to the destination for that case instead of wasting time testing the bit pattern and branching to unreachable. Fixes rdar://problem/21093111.
Reapplying now that Adrian fixed the debug info issue this exposed.
Swift SVN r29202
It would overflow when a type had more than sizeof(unsigned) occupied bits. Fixes rdar://problem/21126703, now with the 64-bit-specific tests properly platform-gated.
Swift SVN r29159
Stupid typo on my part. Fixes a new IRGen bug introduced by the EnumPayload code that's affecting rdar://problem/21126703; not sure if it addresses that bug yet though.
Swift SVN r29116
It's not worth burning more than three registers on a parameter, and doing so causes code size issues for large structs and enums. Make it so that values with more than three explosion members get passed indirectly, just like they get returned indirectly.
This time, modify emitPartialApplyForwarder not to attempt to 'tail' call the original function when indirect arguments get alloca'ed on the stack, which is UB, and don't use "byval", as suggested by John.
Swift SVN r29032
This may be the cause of a crash and burn on the iOS builders:
Assertion failed: (Offset <= PieceOffset && "overlapping or duplicate pieces"), function finalize
Swift SVN r29027
If an enum has only a single tag bit, emit a cond_br instead of a switch, and if it has only one no-payload case, jump directly to the destination for that case instead of wasting time testing the bit pattern and branching to unreachable. Fixes rdar://problem/21093111.
Swift SVN r29023
It's not worth burning more than three registers on a parameter, and doing so causes code size issues for large structs and enums. Make it so that values with more than three explosion members get passed indirectly, just like they get returned indirectly.
Swift SVN r29016
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