Commit Graph

394 Commits

Author SHA1 Message Date
Robert Widmann
d6fe1e9d39 Teach IRGen to Emit Invalid @objc Enums
In order to remove the enum raw value check request in validateDecl,
IRGen must now tolerate recieving an invalid raw value expression.
Switch the assert to instead check for this condition and emit an
invalid negative discriminator.
2019-10-14 15:29:43 -07:00
Robert Widmann
2fe3ce8af8 Requestify the Raw Value Accessor
Make getRawValueExpr() return a checked value.

This entails a strange kind of request that effectively acts like
a cache warmer.  In order to properly check the raw value expression for
a single case, we actually need all the other cases for the
autoincrementing synthesis logic.  The strategy is therefore to have the
request act at the level of the parent EnumDecl and check all the values
at once.  We also cache at the level of the EnumDecl so the cache
"warms" for all enum elements simultaneously.

The request also abuses TypeResolutionStage to act as an indicator for
how much information to compute.  In the minimal case, we will return
a complete accounting of (auto-incremented) raw values.  In the maximal
case we will also check and record types and emit diagnostics.  The
minimal case is uncached to support repeated evaluation.

Note that computing the interface type of an @objc enum decl *must*
force this request.  The enum's raw values are part of the ABI, and we
should not get all the way to IRGen before discovering that we cannot
possibly lay out the enum.  In the future, we might want to consider
moving this check earlier or have IRGen tolerate broken cases but for
now we will maintain the status quo and not have IRGen emit
diagnostics.
2019-10-02 16:09:25 -07:00
Robert Widmann
792e1db448 Port getInterfaceType() patterns in ancillary libraries 2019-09-23 16:49:51 -07:00
Slava Pestov
a0e160e215 AST: Refactor Decl::isWeakImported() API a little bit
First, remove the AvailabilityContext parameter; it was confusing because
we actually always want to use the deployment target here.

Then, split this method up into three methods:

- isAlwaysWeakImported(): simply checks for a @_weakLinked attribute, either
  on the declaration itself or one of its parent contexts.

- getAvailabilityForLinkage(): returns the OS version availability when
  this declaration was introduced, or if the declaration does not have
  explicit availability, check it's storage (if its an accessor), or its
  parent contexts.

- isWeakImported(ModuleDecl *fromModule): combines these two checks to
  determine if the declaration should be weak linked when referenced from
  the given module, or if it might be weak referenced from some module
  (if the module parameter is null).
2019-09-06 20:08:40 -04:00
Slava Pestov
19344e0f1a IRGen: Fix crash if the type of a class stored property hasn't been validated yet
This is a regression from recent changes to make finalizeDecl() do
less work. All these resolveDeclSignature() calls will hopefully go
away soon, once validateDecl() is refactored into a getInterfaceType()
request.
2019-08-07 17:33:09 -04:00
Michael Munday
bb2740e540 IRGen: fix enum bit packing on big-endian platforms.
This change modifies spare bit masks so that they are arranged in
the byte order of the target platform. It also modifies and
consolidates the code that gathers and scatters bits into enum
values.

All enum-related validation tests are now passing on IBM Z (s390x)
which is a big-endian platform.
2019-08-07 03:54:16 -04:00
pschuh
64d0c426ff [C++ Interop] Uninhabitted enums are still possible. (#26451) 2019-08-05 15:52:04 -07:00
pschuh
34bfeb4212 [C++ interop] Fix reflection info compiler crash. (#26438)
When a c++ namespace IRGens for reflection, it triggers a path that
expects the namespace to have a particular form. Because it is always
empty, we can treat it just like an empty swift enum.
2019-08-01 15:20:03 -07:00
Slava Pestov
7a4e7eda00 IRGen: Don't get enum element argument type until we need it
Instead of adding a resolveDeclSignature() call here, I'm going to live
dangerously and try to only get the enum element type in the case where
SIL type lowering has already computed it, that is, if the enum is not
indirect.

Soon this will become moot anyway because getInterfaceType() will be a
request.
2019-07-17 18:07:03 -04:00
Arnold Schwaighofer
2b5267046d Reformat. NFC. 2019-06-25 12:20:13 -07:00
Arnold Schwaighofer
6f4c5c48ce IRGen: Correctly compute fixed sized'ness of resilient enums
rdar://51422528
2019-06-25 11:57:56 -07:00
Michael Munday
931eccb34d IRGen: simplify code generation for enum switch statements
This change uses the 'gather bits' functionality of enum payloads
to create a contiguous value to switch over. This allows us to
remove the code that currently attempts to build a switch statement
by comparing each element in the payload in turn.

The downside of this technique is that we may do more work up front
gathering bits and we may also need to compare larger values in some
situations. The upside is that we can remove a lot of complicated
code from IRGen. Also, we pass the responsibility for multi-way
branch generation to LLVM which can make use of a wider range of
switch lowering strategies than IRGen can sensibly support.
2019-06-19 14:57:12 +01:00
Davide Italiano
aef830d4a4 [GenEnum] Fix getBitMaskForNoPayloadElements.
Based on a patch from Joe Groff. This is only triggered in
lldb so I'll add a test there.

<rdar://problem/51211938>
2019-06-07 11:14:33 -07:00
Michael Munday
253d5b5d18 [IRGen] Simplify constant occupied/spare bit interleaving
Add a new scatterBits function that is simpler and more generic
than the old interleaveSpareBits function. It is essentially a
constant version of the emitScatterBits function.
2019-05-22 16:19:01 +01:00
Michael Munday
d3262ec10d [IRGen] Remove SetBitEnumerator from ClusteredBitVector
The change replaces 'set bit enumeration' with arithmetic
and bitwise operations. For example, the formula
'(((x & -x) + x) & x) ^ x' can be used to find the rightmost
contiguous bit mask. This is essentially the operation that
SetBitEnumerator.findNext() performed.

Removing this functionality reduces the complexity of the
ClusteredBitVector (a.k.a. SpareBitVector) implementation and,
more importantly, API which will make it easier to modify
the implementation of spare bit masks going forward. My end
goal being to make spare bit operations work more reliably on
big endian systems.

Side note:

This change modifies the emit gather/scatter functions so that
they work with an APInt, rather than a SpareBitVector, which
makes these functions a bit more generic. These functions emit
instructions that are essentially equivalent to the parallel bit
extract/deposit (PEXT and PDEP) instructions in BMI2 on x86_64
(although we don't emit those directly currently). They also map
well to bitwise manipulation instructions on other platforms (e.g.
RISBG on IBM Z). So we might find uses for them outside spare bit
manipulation in the future.
2019-05-17 11:55:06 +01:00
Michael Munday
25a075cbb6 [IRGen] Remove unused explosion schema from enum payload schema
At some point it might be useful to be able to use an appropriate
explosion schema to explode payloads but currently the code that
handles this is unused. There are lots of different ways we might
add this functionality in the future and it isn't clear that the
existing code will be the best way to use explosion schemas in the
future.

For now remove this dead code so that its presence doesn't obscure
the code that is actually in use.
2019-05-10 12:15:11 +01:00
Arnold Schwaighofer
e2d3f533d6 IRGen: Intialize single case enum extrainhabitant value witness in generated code
Older Swift runtimes miss this initialization in the swift_initEnumMetadataSingleCase runtime call.

rdar://49786768
2019-04-25 14:19:56 -07:00
Slava Pestov
af83492a45 IRGen: Lazily emit reflection field descriptors
Previously even if a type's metadata was optimized away, we would still
emit a field descriptor, which in turn could reference nominal type
descriptors for other types via symbolic references, etc.
2019-04-12 01:46:23 -04:00
Slava Pestov
6d2fc0c08c IRGen: Change around how we decide to emit lazy type metadata
The old logic was confusing. The LazyTypeGlobals map would contain
entries for all referenced types, even those without lazy metadata.

And for a type with lazy metadata, the IsLazy field would begin
with a value of false -- unless it was imported.

When a non-imported type was finally visited in the AST, we would
try to "enable" lazyness for it, which meant queueing up any
metadata that had been requested prior, or immediately emitting
the metadata otherwise.

Instead, let's add a separate map that caches whether a type has
lazy metadata or not. The first time we ask for the metadata of a
type, consult this map. If the type has lazy metadata according to
the map, queue up metadata emission for the type. Otherwise, emit
metadata eagerly when the type is visited in the AST.
2019-04-12 01:46:23 -04:00
Slava Pestov
61f21a7195 IRGen: Emit field reflection descriptors for types with custom alignment
The code to decide if field descriptors were going to be emitted was
confusing, so I've refactored it a bit.
2019-04-12 01:46:23 -04:00
Arnold Schwaighofer
ac4330a39f IRGen: Test all of the payload bits if there are not extra inhabitants
rdar://49380548
2019-03-28 14:26:52 -07:00
Saleem Abdulrasool
3192eb3221 Merge pull request #22208 from linux-on-ibm-z/s390x-storetag-fix
Fix storeEnumTagSinglePayload on big-endian systems
2019-03-21 14:18:12 -07:00
Slava Pestov
980fb7c437 SIL: Remove default resilience expansion from isTypeABIAccessible() 2019-03-06 02:26:26 -05:00
Slava Pestov
69d1cafd1c AST: Add AvailabilityContext parameter to Decl::isWeakImported()
For now, it's not used, but we do try to pass the right value down from
our various call sites.

Progress on <rdar://problem/46674512>.
2019-02-19 18:58:44 -05:00
Joe Groff
4b6775699c IRGen: Mask all spare bits in multi-payload enums when injecting the tag.
Single-payload enum layout unfortunately assumes that constructing the payload case is a no-op, such
as when building Optional.some(x) for a value x. For multi-payload enums, now that we use the unused
spare bits to form extra inhabitants when the enum is in turn wrapped in an Optional or other single-
payload enum, this means we have to zero all of those bits. The spare bits may have been selected from
intra-field or tail padding bytes that are undefined in the underlying payload types. Fixes
rdar://problem/47635801.
2019-02-01 09:47:31 -08:00
Michael Munday
43bfbd5f38 Use llvm::Triple to test target endianness
The current checks won't work when cross compiling from a machine
with a different endianness to the target.
2019-01-30 06:46:43 -05:00
Arnold Schwaighofer
5ae00ee2a2 IRGen: Conditionally test weakly linked enum cases
rdar://46438568
2018-12-12 11:18:12 -08:00
John McCall
724c192120 Propagate the XI count into the get/store XI tag callbacks.
This allows callers to avoid needing to reload these tags in common cases.
2018-12-11 22:18:44 -05:00
John McCall
2ba7090fe8 Remove the extra-inhabitant value witness functions.
This is essentially a long-belated follow-up to Arnold's #12606.
The key observation here is that the enum-tag-single-payload witnesses
are strictly more powerful than the XI witnesses: you can simulate
the XI witnesses by using an extra case count that's <= the XI count.
Of course the result is less efficient than the XI witnesses, but
that's less important than overall code size, and we can work on
fast-paths for that.

The extra inhabitant count is stored in a 32-bit field (always present)
following the ValueWitnessFlags, which now occupy a fixed 32 bits.
This inflates non-XI VWTs on 32-bit targets by a word, but the net effect
on XI VWTs is to shrink them by two words, which is likely to be the
more important change.  Also, being able to access the XI count directly
should be a nice win.
2018-12-11 22:18:44 -05:00
Slava Pestov
6926fde2da IRGen: Tiny cleanup in GenEnum.cpp 2018-12-10 00:00:49 -05:00
Joe Groff
bf593b420c IRGen: Fix extra inhabitants of multi-payload enums with more spare bits than tag bits.
Because layout minimizes the number of tag bits used, and favors high spare bits, the
spare bit representations end up overlapping the extra inhabitant representations, since we
just counted down from -1. If there are fewer tag bits than total spare bits, rotate the
extra inhabitant values so they correctly line up with the tag representations in this
situation. rdar://problem/46468090
2018-12-06 13:01:04 -08:00
Joe Groff
32749f331a Merge pull request #20561 from jckarter/multi-payload-xi
Give multi-payload enums extra inhabitants.
2018-11-13 20:41:19 -08:00
Joe Groff
ca402f19b1 Give multi-payload enums extra inhabitants.
Previously, they would forward their unused spare bits to be used by other multi-payload enums, but
did not implement anything for single-payload extra inhabitants.
2018-11-13 18:08:01 -08:00
Saleem Abdulrasool
2117c46097 IRGen: add a constant for common linkages
Swift uses LinkOnceODR with Internal linkage and normal Internal linkage quite
frequently.  Define a constant for this.
2018-11-13 09:56:24 -08:00
Saleem Abdulrasool
86e5b2574c IRGen: introduce new IRLinkage applicator
In order to handle LinkOnceODR semantics correctly across various object
formats, introduce a new helper ApplyIRLinkage.  This abstracts the need
to create a COMDAT group and set it on the GlobalValue.  Adjust all
sites where we set the IR linkage attributes to use this mechanism
instead to avoid having to track down symbols not being added to a
COMDAT group.
2018-11-04 10:13:50 -08:00
John McCall
2d70a03c34 [NFC] Improve the interfaces for integer widths and parsing integers 2018-10-31 12:45:52 -04:00
Slava Pestov
87ec607233 IRGen: Add a new 'Legacy' lowering mode that loads type info from a YAML file
The YAML format is the same one produced by the -dump-type-info
frontend mode.

For now this is only enabled if the -read-type-info-path frontend
flag is specified.

Progress on <rdar://problem/17528739>.
2018-10-04 23:33:17 -04:00
Slava Pestov
73aff74e8d IRGen: Type lowering cache doesn't need to store 'forward declarations' 2018-10-04 20:01:23 -04:00
Joe Groff
9f02ecd1a5 IRGen: Use any field of structs for extra inhabitants.
This allows us to layout-optimize Optional<T> when T is a struct with an
extra-inhabitant-bearing field anywhere in its definition, not only at
the beginning. rdar://problem/43019427
2018-08-14 12:53:06 -07:00
Slava Pestov
9f5505d95c IRGen: Don't make values constant in getAddrOfSimpleVariable()
We also use this for field offset globals, which are not always
constant. I think in practice everything was getting set
correctly, but it was hard to follow the logic.
2018-08-10 00:42:34 -07:00
Slava Pestov
d460d5def6 IRGen: Remove ASTTy field from StructLayout 2018-08-07 04:26:43 -07:00
Bob Wilson
ffa88c3d28 Merge remote-tracking branch 'origin/master' into master-next 2018-07-23 14:38:55 -07:00
Bob Wilson
8e330ee344 NFC: Fix indentation around the newly renamed LLVM_DEBUG macro.
Jordan used a sed command to rename DEBUG to LLVM_DEBUG. That caused some
lines to wrap and messed up indentiation for multi-line arguments.
2018-07-21 00:56:18 -07:00
Jordan Rose
cefb0b62ba Replace old DEBUG macro with new LLVM_DEBUG
...using a sed command provided by Vedant:

$ find . -name \*.cpp -print -exec sed -i "" -E "s/ DEBUG\(/ LLVM_DEBUG(/g" {} \;
2018-07-20 14:37:26 -07:00
Bob Wilson
5df3d1f100 Merge remote-tracking branch 'origin/master' into master-next 2018-06-14 20:51:48 -07:00
Arnold Schwaighofer
a8fee28fb0 IRGen: Don't outline enum value functions when they involve open existential types
We don't support doing so.

rdar://41009775
2018-06-13 12:48:35 -07:00
swift-ci
891b28f73b Merge remote-tracking branch 'origin/master' into master-next 2018-05-31 09:49:41 -07:00
Arnold Schwaighofer
95e31eefa2 IRGen: Fix multipayload enums with indirect cases
swift_unknownRetain does not work on indirect enum heap buffers.

The existing logic would say: oh one case is
ReferenceCounting::BridgeObject (which on its own probably would not
work with swift_unknownRetain), oh and another second case is NativeObject (for
the indirect buffer), let's use unknowRetain.

Pair the logic down to only use a single style of reference count
operation if all cases are of the same ReferenceCounting type.

rdar://40525268
2018-05-30 15:46:06 -07:00
Vedant Kumar
105a61e50d Use LLVM_DEBUG() instead of DEBUG()
Upstream has renamed the DEBUG() macro to LLVM_DEBUG. This updates swift
accordingly:

$ find . -name \*.cpp -print -exec sed -i "" -E "s/ DEBUG\(/ LLVM_DEBUG(/g" {} \;
2018-05-24 13:10:45 -07:00
swift-ci
2714ed70c6 Merge remote-tracking branch 'origin/master' into master-next 2018-05-15 14:09:30 -07:00