Commit Graph

167 Commits

Author SHA1 Message Date
Slava Pestov
2be7dc0de9 IRGen: Fix stupid oversight in emission of fixed multi-payload enum vw_getEnumTag()
The payload tag discriminates between payload cases, but empty cases
are stored in the common spare bits of the payload types, so the logic
here would report all empty cases as having the first empty case selected.
And when writing tests, I didn't cover enums with multiple empty *and*
non-empty cases. Oops...

Now we emit a little bit more code to assemble the correct case index
from both the payload tag and payload value, then select between the
two values depending on the payload tag.

Fixes <rdar://problem/22192074>.

Swift SVN r31328
2015-08-19 04:31:36 +00:00
Joe Groff
a806943d02 IRGen: Allow empty-type enum payloads to be projected.
We can still produce an undefined address for the empty value, even though we considered them as no-payload cases for layout purposes. Fixes rdar://problem/21515490.

Swift SVN r30490
2015-07-22 05:10:47 +00:00
Joe Groff
ec61fa4c5a IRGen/Runtime: Use only the 'layout' subset of the vwtable to perform value type layout.
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
2015-07-16 15:38:17 +00:00
Slava Pestov
a043ae797b IRGen: Small cleanup in GenEnum.cpp, NFC
Swift SVN r30254
2015-07-16 07:08:38 +00:00
Ted Kremenek
a3d88266b2 Revert "IRGen/Runtime: Use only the 'layout' subset of the vwtable to perform value type layout."
This reverts commit r30243.

This appears to be breaking the Linux build.

Swift SVN r30253
2015-07-16 06:28:24 +00:00
Joe Groff
2641d566ac IRGen/Runtime: Use only the 'layout' subset of the vwtable to perform value type layout.
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
2015-07-16 01:28:42 +00:00
Mark Lacey
37a70ef1b3 Fix conditional branch generation for switch_enum.
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
2015-07-15 22:05:52 +00:00
Slava Pestov
cdd5a4121c IRGen: Generate value witnesses to get enum tag and project payload
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
2015-07-15 06:03:18 +00:00
Joe Groff
734891e0fa IRGen: Don't store the masked refcounted payload when copying multi-payload enums.
Fixes rdar://problem/21707972.

Swift SVN r30055
2015-07-10 02:58:00 +00:00
Doug Gregor
3023a710fc Split TypeBase::isDependentType() into isTypeParameter() and hasTypeParameter().
The isDependentType() query is woefully misunderstood. Some places
seem to want it to mean "a generic type parameter of dependent member
type", which corresponds to what is effectively a type parameter in
the language, while others want it to mean "contains a type parameter
anywhere in the type". Tease out these two meanings in
isTypeParameter() and hasTypeParameter(), respectively, and sort out
the callers.

Swift SVN r29945
2015-07-07 21:20:54 +00:00
Joe Groff
bd9a3ce9ae IRGen: Break recursion when lowering indirect enum cases.
The type metadata for Builtin.NativeObject stands in well enough for a box without needing to descend into the payload recursively.

Swift SVN r29834
2015-07-01 04:51:52 +00:00
Dmitri Hrybenko
2fc1cbe8c1 Adjust to the new IRBuilder APIs
Swift SVN r29692
2015-06-25 22:01:24 +00:00
Mark Lacey
ef1886a4c1 Fix crash generating IR for select_enum with payload that has no extra inhabitants.
We were crashing grabbing the extra inhabitant mask, which does not
always exist. Instead, test to see if there are extra inhabitants and
only use that mask in the comparison if there are in fact extra
inhabitants in the enum layout.

Fixes rdar://problem/21514065.

Swift SVN r29662
2015-06-25 09:39:47 +00:00
Joe Groff
76b9838564 IRGen: Peephole improvements for enum switch codegen.
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
2015-06-01 19:17:54 +00:00
Mark Lacey
7aec3c2d2b Remove TypeInfo::isIndirectArgument() since it is unused.
Swift SVN r29076
2015-05-27 21:06:12 +00:00
Ted Kremenek
c60b51be69 Revert "IRGen: Peephole improvements for enum switch codegen."
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
2015-05-26 06:06:43 +00:00
Joe Groff
c8238ffb17 IRGen: Peephole improvements for enum switch codegen.
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
2015-05-26 04:53:43 +00:00
Mark Lacey
1d334f06c7 Remove asserts that cause compilation failures on Linux.
The Linux assert() is apparently doing a positive test on the value,
whereas the Darwin assert() is negating it.

APInt has an operator!(), but APInt cannot be implicitly converted to a
bool, so directly testing the value caused issues only on the Linux
build.

JoeG says the asserts were testing pointer nullness before his recent
representation changes, and aren't meaningful with the new
representation, so they should just be removed.

Swift SVN r29011
2015-05-25 18:56:58 +00:00
Joe Groff
79dc6db4bb IRGen: Redesign enum codegen to break payloads into word-sized chunks.
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
2015-05-24 16:20:21 +00:00
Ted Kremenek
bbf61217cd Revert "IRGen: Redesign enum codegen to break payloads into word-sized chunks."
This is asserting on the bots:

Assertion failed: ((~mask & value) == 0 && "value has masked out bits set?!"), function emitCompare

Swift SVN r28983
2015-05-24 05:38:53 +00:00
Joe Groff
3691991374 IRGen: Redesign enum codegen to break payloads into word-sized chunks.
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
2015-05-24 05:23:23 +00:00
Slava Pestov
e6dbc2a171 IRGen: Don't emit enum case names for C-compatible enums
Until we start saving the rawValue to case name mapping, we can't
do anything with this.

Swift SVN r28428
2015-05-11 18:21:38 +00:00
Joe Groff
03cff119f5 IRGen: Don't try to pack a nonexistent empty payload from a single-payload enum nested into an outer enum.
Fixes rdar://problem/20882920.

Swift SVN r28405
2015-05-11 00:20:45 +00:00
Joe Groff
2d3eba9e0d IRGen: Reuse value witness table projections.
Don't project every value witness from the metadata every time we need one; this wastes code size in a way LLVM can't really optimize since it doesn't know the metadata is immutable. The code size wins on the standard library are disappointingly small (stdlib only shrinks by 4KB), but this makes generic IR a lot more compact and easier to read.

Swift SVN r28095
2015-05-03 05:00:40 +00:00
Andrew Trick
a174aa4dfe Add AST and SILGen support for Builtin.isUnique.
Preparation to fix <rdar://problem/18151694> Add Builtin.checkUnique
to avoid lost Array copies.

This adds the following new builtins:

    isUnique : <T> (inout T[?]) -> Int1
    isUniqueOrPinned : <T> (inout T[?]) -> Int1

These builtins take an inout object reference and return a
boolean. Passing the reference inout forces the optimizer to preserve
a retain distinct from what’s required to maintain lifetime for any of
the reference's source-level copies, because the called function is
allowed to replace the reference, thereby releasing the referent.

Before this change, the API entry points for uniqueness checking
already took an inout reference. However, after full inlining, it was
possible for two source-level variables that reference the same object
to appear to be the same variable from the optimizer's perspective
because an address to the variable was longer taken at the point of
checking uniqueness. Consequently the optimizer could remove
"redundant" copies which were actually needed to implement
copy-on-write semantics. With a builtin, the variable whose reference
is being checked for uniqueness appears mutable at the level of an
individual SIL instruction.

The kind of reference count checking that Builtin.isUnique performs
depends on the argument type:

    - Native object types are directly checked by reading the
      strong reference count:
      (Builtin.NativeObject, known native class reference)

    - Objective-C object types require an additional check that the
      dynamic object type uses native swift reference counting:
      (Builtin.UnknownObject, unknown class reference, class existential)

    - Bridged object types allow the dymanic object type check to be
      bypassed based on the pointer encoding:
      (Builtin.BridgeObject)

Any of the above types may also be wrapped in an optional.  If the
static argument type is optional, then a null check is also performed.

Thus, isUnique only returns true for non-null, native swift object
references with a strong reference count of one.

isUniqueOrPinned has the same semantics as isUnique except that it
also returns true if the object is marked pinned regardless of the
reference count. This allows for simultaneous non-structural
modification of multiple subobjects.

In some cases, the standard library can dynamically determine that it
has a native reference even though the static type is a bridge or
unknown object. Unsafe variants of the builtin are available to allow
the additional pointer bit mask and dynamic class lookup to be
bypassed in these cases:

    isUnique_native : <T> (inout T[?]) -> Int1
    isUniqueOrPinned_native : <T> (inout T[?]) -> Int1

These builtins perform an implicit cast to NativeObject before
checking uniqueness. There’s no way at SIL level to cast the address
of a reference, so we need to encapsulate this operation as part of
the builtin.

Swift SVN r27887
2015-04-28 22:54:24 +00:00
Joe Groff
bdac5fe1c8 IRGen: Implement emitIndirectCaseTest for dynamic multi-payload enums.
The last little bit of unimplemented code for dynamic enums.

Swift SVN r27814
2015-04-27 19:37:18 +00:00
Joe Groff
889b8d3826 IRGen: Fix implementation of emitValueCaseTest for multi-payload enums.
Empty cases are packed into the payload under a minimal number of tags, instead of having once case per tag, as for payload cases.

Swift SVN r27813
2015-04-27 19:37:18 +00:00
Joe Groff
0126311e23 Enable dynamic multi-payload enums.
Fixes rdar://problem/15666173.

Swift SVN r27792
2015-04-27 00:35:13 +00:00
Joe Groff
3dafb24b5d IRGen: Call the runtime to initialize dynamic multi-payload enum metadata.
Emit a call to a third and final to-be-implemented runtime function to help instantiate the metadata of a dynamic multi-payload enum.

Swift SVN r27790
2015-04-27 00:35:07 +00:00
Joe Groff
0b339b9a46 IRGen: Populate nominal type descriptor metadata for enums.
Store the number of payload and no-payload cases, the case names, and a lazy case type accessor function for enums, like we do for stored properties of structs and classes. This will be useful for multi-payload runtime support, and should also be enough info to hack together a reflection implementation for enums.

For dynamic multi-payload enums to not be ridiculously inefficient, we'll need to track the size of the payload area in the enum, like we do the field offsets of generic structs and classes, so hack off a byte in the payload case count to track the offset of that field in metadata records. 16 million payloads ought to be enough for anyone, right? (and 256 words between the enum metadata's address point and the payload size offset)

Swift SVN r27789
2015-04-27 00:35:04 +00:00
Joe Groff
6349fd7726 IRGen: Bitwise-take peepholes for multi-payload enums.
Do initializeWithTake by bitwise-copy on multi-payload enums when possible.

Swift SVN r27788
2015-04-27 00:34:59 +00:00
Joe Groff
fbf7c9c3c8 IRGen: Value semantics for dynamic multi-payload enums.
Refactor some things so that the copy_addr implementation for multi-payload enums works with dynamic as well as fixed cases.

Swift SVN r27787
2015-04-27 00:34:56 +00:00
Joe Groff
ff2d1df7af IRGen: Switching for dynamic multi-payload enums.
Use a different yet-to-be-implemented runtime call to extract the tag from a dynamic-layout enum so we can switch it.

Swift SVN r27786
2015-04-27 00:34:54 +00:00
Joe Groff
27266ff08a IRGen: Codegen for dynamic multi-payload tag injections.
Emit a call to an as-yet-unwritten runtime function that will perform the injection.

Swift SVN r27784
2015-04-27 00:34:49 +00:00
Joe Groff
c3bb5e7451 IRGen: Handle empty payloads in multi-payload enum layout.
This can come up now when generic multi-payload enums substitute in empty types for all their payloads. It's also an opportunity to factor things a bit so that they're easier to extend to dynamic cases.

Swift SVN r27783
2015-04-27 00:34:47 +00:00
Joe Groff
723697f421 IRGen: Don't use spare bits in fixed instances of dependent multi-payload enums.
We don't want to wait to revamp the runtime to track spare bits in order to get multi-payload enum cases working, so when lowering an enum, track when the generic enum type's layout is dependent, and constrain our use of spare bits when it is.

Swift SVN r27781
2015-04-27 00:34:38 +00:00
Joe Groff
e4e0f35aed IRGen: Implement an @_alignment attribute.
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
2015-04-15 17:23:30 +00:00
Chris Lattner
c1bc639d7b add an IRGen peephole for lowering certain switch_enum's that commonly
come up when pattern matching on optional.  Instead of expanding to a
switch with a default and one case, expand to an icmp and condbr.



Swift SVN r26090
2015-03-13 05:14:49 +00:00
Dmitri Hrybenko
61286f0260 Fix warnings produced by a newer version of Clang
Swift SVN r25257
2015-02-12 23:50:47 +00:00
Joe Groff
00f0286886 IRGen: Mask the payload of nested single-payload enum payloads.
Fixes rdar://problem/18841262.

Swift SVN r24908
2015-02-02 23:29:21 +00:00
Jordan Rose
4fae1f664f [IRGen] Remove the AST walk that looks for local type decls.
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
2015-01-30 03:54:08 +00:00
Chris Lattner
5ddc776efa The Payload case of SinglePayloadEnumImplStrategy is more complicated than
I thought.  Apparently there is no way to directly test whether a general
enum contains the payload without testing against each of the potential 
inhabitant cases with a switch.  Instead of solving this open problem, just
optimize the case where we're testing for a single non-payload case, and 
special case enums with one payload and one non-payload case (hello optional!)
by testing for the non-payload case and inverting the result.  This resolves
the miscompilations I was seeing before with my full patch set, but is still
NFC since the code that uses this isn't included yet.




Swift SVN r24365
2015-01-11 22:33:01 +00:00
Chris Lattner
2ea05c3adb Add new entry points to the enum implementation strategy for testing an enum against a
specific case and returning an i1 result.  This can be done a lot more efficiently (in
terms of generated LLVM IR) than doing a general switch over the cases.  This will be used
to implement rdar://19404937, but there is a miscompilation here that I'm tracking down.

Until it is working, I'm not committing the code to use these entrypoints, which wires it
into IRGen of SelectEnumInst and SelectEnumAddrInst.  Since that part isn't included, this
is NFC.


Swift SVN r24362
2015-01-11 07:36:53 +00:00
John McCall
275ef489d4 Switch IRGen to use ClusteredBitVector.
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
2015-01-09 21:06:37 +00:00
Dmitri Hrybenko
4caca5d098 Revert "Switch IRGen to use ClusteredBitVector."
This reverts commit r24305.  It broke the standard library build.

Swift SVN r24318
2015-01-09 18:25:21 +00:00
John McCall
6e41b3c742 Switch IRGen to use ClusteredBitVector.
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
2015-01-09 10:05:51 +00:00
Joe Groff
0c05600caa IRGen: Lay out @objc enums in a C-compatible way.
Swift SVN r23424
2014-11-19 04:03:09 +00:00
Erik Eckstein
ec4accfda8 Optimize IRGen of select_num which maps the enum tag trivially to an int value.
This generates a simple int-cast instead of a switch.



Swift SVN r23117
2014-11-05 15:43:10 +00:00
Joe Groff
9205bf64cf SIL: Remove enum_is_tag.
Swift SVN r22616
2014-10-09 05:03:43 +00:00
Jordan Rose
3fcdfd40e9 Remove the "swift/Basic/Optional.h" header.
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
2014-10-02 18:51:45 +00:00