To distinguish between classes which have the same name (but are in different contexts).
Fixes a miscompile if classes with the same name are used from a different module.
SR-10634
rdar://problem/50538534
The ownership kind is Any for trivial types, or Owned otherwise, but
whether a type is trivial or not will soon depend on the resilience
expansion.
This means that a SILModule now uniques two SILUndefs per type instead
of one, and serialization uses two distinct sentinel IDs for this
purpose as well.
For now, the resilience expansion is not actually used here, so this
change is NFC, other than changing the module format.
SILWitnessTable::Entry already contains a superset of what was supported
by SILDefaultWitnessTable::Entry, the latter of which only had “no entry”
and “method” states. Make SILDefaultWitnessTable::Entry an alias for
SILWitnessTable::Entry, and unify all of the parsing/printing/
(de)serialization logic.
...instead of std::vector, which (1) will always make separate
allocations, and (2) has features and overhead we don't need
I don't expect this to actually affect performance too much, but it
seems more correct for what Serialization needs anyway.
Previously SILModule contained two different pathways for the deserializer to
send notifications that it had created functions:
1. A list of function pointers that were called when a function's body was
deserialized. This was added recently so that access enforcement elimination is
run on newly deserialized SIL code if we have already eliminated access
enforcement from the module.
2. SILModule::SerializationCallback. This is an implementation of the full
callback interface and is used by the SILModule to update linkage and other
sorts of book keeping.
To fix the pass manager notification infrastructure, I need to be able to send
notifications to a SILPassManager when deserializing. I also need to be able to
eliminate these callbacks when a SILPassManager is destroyed. These requirements
are incompatible with the current two implementations since: (2) is an
implementation detail of SILModule and (1) only notifies on function bodies
being deserialized instead of the creation of new declarations (what the caller
analysis wants).
Rather than adding a third group of callbacks, this commit refactors the
infrastructure in such a way that all of these use cases can use one
implementation. This is done by:
1. Lifting the interface of SerializedSILLoader::Callback into a base
notification protocol for deserialization called
DeserializationNotificationHandlerBase and its base no-op implementation into an
implementation of the aforementioned protocol:
DeserializationNotificationHandler.
2. Changing SILModule::SerializationCallback to implement
DeserializationNotificationHandler.
3. Creating a class called FunctionBodyDeserializationNotificationHandler that
takes in a function pointer and uses that to just override the
didDeserializeFunctionBody. This eliminates the need for the specific function
body deserialization list.
4. Replacing the state associated with the two other pathways with a single
DeserializationNotificationHandlerSet class that contains a set of
DeserializationNotificationHandler and chains notifications to them. This set
implements DeserializationNotificationHandlerBase so we know that its
implementation will always be in sync with DeserializationNotificationHandler.
rdar://42301529
Now that @inlinable is a supported feature, we need to handle cases
where a function is inlinable but it references some type that imports
differently in different Swift versions. To start, handle the case
where a SIL function's type is now invalid and therefore the entire
function can't be imported. This doesn't open up anything interesting
yet, but it's a start.
Part of rdar://problem/40899824
Client code can make a best effort at emitting a key path referencing a property with its publicly exposed API, which in the common case will match what the defining module would produce as the canonical key path component representation of the declaration. We can reduce the code size impact of these descriptors by not emitting them when there's no hidden or possibly-resiliently-changed-in-the-past information about a storage declaration, having the property descriptor symbol reference a sentinel value telling client key paths to use their definition of the key path component.
Wire up the request-evaluator with an instance in ASTContext, and
introduce two request kinds: one to retrieve the superclass of a class
declaration, and one to compute the type of an entry in the
inheritance clause.
Teach ClassDecl::getSuperclass() to go through the request-evaluator,
centralizing the logic to compute and extract the superclass
type.
Fixes the crasher from rdar://problem/26498438.
This reverts commit 1b3d29a163, reversing
changes made to b32424953e.
We're seeing a handful of issues from turning on inlining of generics,
so I'm reverting to unblock the bots.
The reason we are using the parsing heuristic is to ensure that we do
not need to update a ton of test cases. This makes sense since in
general, when parsing we are creating new code that is running for the
first time through the compiler. On the other hand, in
serialization/deserialization we expect to get back exactly the
SILFunction that we serialized. So it makes sense to explicitly
preserve whether we have ownership qualification or not.
rdar://28851920
Over the past day or so I have been thinking about how we are going to need to
manage verification of semantic ARC semantics in the pass pipeline. Specifically
the Eliminator pass really needs to be a function pass to ensure that we can
transparently put it at any stage of the optimization pipeline. This means that
just having a flag on the SILVerifier that states whether or not ownership is
enabled is not sufficient for our purposes. Instead, while staging in the SIL
ownership model, we need a bit on all SILFunctions to state whether the function
has been run through the ownership model eliminator so that the verifier can
ensure that we are in a world with "SIL ownership" or in a world without "SIL
ownership", never in a world with only some "SIL ownership" instructions. We
embed this distinction in SIL by creating the concept of a function with
"qualified ownership" and a function with "unqualified ownership".
Define a function with "qualified ownership" as a function that contains no
instructions with "unqualified ownership" (i.e. unqualified load) and a function
with "unqualified ownership" as a function containing such no "ownership
qualified" instructions (i.e. load [copy]) and at least 1 unqualified ownership
instruction.
This commit embeds this distinction into SILFunction in a manner that is
transparently ignored when compiling with SIL ownership disabled. This is done
by representing qualified or unqualified ownership via an optional Boolean on
SILFunction. If the Boolean is None, then SILOwnership is not enabled and the
verifier/passes can work as appropriate. If the Boolean is not None, then it
states whether or not the function has been run through the Ownership Model
Eliminator and thus what invariants the verifier should enforce.
How does this concept flow through the compilation pipeline for functions in a
given module? When SIL Ownership is enabled, all SILFunctions that are produced
in a given module start with "qualified ownership" allowing them to contain SIL
ownership instructions. After the Ownership Model eliminator has run, the
Ownership Model sets the "unqualified" ownership flag on the SILFunction stating
that no more ownership qualified instructions are allowed to be seen in the
given function.
But what about functions that are parsed or are deserialized from another
module? Luckily, given the manner in which we have categories our functions, we
can categorize functions directly without needing to add anything to the parser
or to the deserializer. This is done by enforcing that it is illegal to have a
function with qualified ownership and unqualified ownership instructions and
asserting that functions without either are considered qualified.
rdar://28685236
My earlier patch started serializing SIL basic blocks using the RPOT order. While it works, changing the existing order of BBs during the serialization may be very surprising for users. After all, serialization is not supposed to transform the code.
Therefore, this patch follows a different approach. It uses the existing order of BBs during the serialization. When it deserializes SIL and detects a use of an opened archetype before its definition, it basically introduced a forward definition of this opened archetype. Later on, when the actual definition of the opened archetype is found, it replaces the forward definition. There is a correctness check at the end of a SIL function deserialization, which verifies that there are no forward definitions of opened archetypes left unresoved.
Till now there was no way in SIL to explicitly express a dependency of an instruction on any opened archetypes used by it. This was a cause of many errors and correctness issues. In many cases the code was moved around without taking into account these dependencies, which resulted in breaking the invariant that any uses of an opened archetype should be dominated by the definition of this archetype.
This patch does the following:
- Map opened archetypes to the instructions defining them, i.e. to open_existential instructions.
- Introduce a helper class SILOpenedArchetypesTracker for creating and maintaining such mappings.
- Introduce a helper class SILOpenedArchetypesState for providing a read-only API for looking up available opened archetypes.
- Each SIL instruction which uses an opened archetype as a type gets an additional opened archetype operand representing a dependency of the instruction on this archetype. These opened archetypes operands are an in-memory representation. They are not serialized. Instead, they are re-constructed when reading binary or textual SIL files.
- SILVerifier was extended to conduct more thorough checks related to the usage of opened archetypes.
Till now there was no way in SIL to explicitly express a dependency of an instruction on any opened archetypes used by it. This was a cause of many errors and correctness issues. In many cases the code was moved around without taking into account these dependencies, which resulted in breaking the invariant that any uses of an opened archetype should be dominated by the definition of this archetype.
This patch does the following:
- Map opened archetypes to the instructions defining them, i.e. to open_existential instructions.
- Introduce a helper class SILOpenedArchetypesTracker for creating and maintaining such mappings.
- Introduce a helper class SILOpenedArchetypesState for providing a read-only API for looking up available opened archetypes.
- Each SIL instruction which uses an opened archetype as a type gets an additional opened archetype operand representing a dependency of the instruction on this archetype. These opened archetypes operands are an in-memory representation. They are not serialized. Instead, they are re-constructed when reading binary or textual SIL files.
- SILVerifier was extended to conduct more thorough checks related to the usage of opened archetypes.
Till now there was no way in SIL to explicitly express a dependency of an instruction on any opened archetypes used by it. This was a cause of many errors and correctness issues. In many cases the code was moved around without taking into account these dependencies, which resulted in breaking the invariant that any uses of an opened archetype should be dominated by the definition of this archetype.
This patch does the following:
- Map opened archetypes to the instructions defining them, i.e. to open_existential instructions.
- Introduce a helper class SILOpenedArchetypesTracker for creating and maintaining such mappings.
- Introduce a helper class SILOpenedArchetypesState for providing a read-only API for looking up available opened archetypes.
- Each SIL instruction which uses an opened archetype as a type gets an additional opened archetype operand representing a dependency of the instruction on this archetype. These opened archetypes operands are an in-memory representation. They are not serialized. Instead, they are re-constructed when reading binary or textual SIL files.
- SILVerifier was extended to conduct more thorough checks related to the usage of opened archetypes.
It it now possible to check if a function with a given name and a given linkage exists in one of the modules,
even if the current module contains a function with this name but a difference linkage.
This is useful e.g. for performing a lookup of pre-specializations.
These APIs are useful e.g. for quickly finding pre-specialisations by their names.
The existence check is very light-weight and does not try to deserialize bodies of SIL functions.
As there are no instructions left which produce multiple result values, this is a NFC regarding the generated SIL and generated code.
Although this commit is large, most changes are straightforward adoptions to the changes in the ValueBase and SILValue classes.
This shouldn't affect anything in practice but it's best to be deterministic.
(Although I'm not sure why the previous mode was nondeterministic.)
Swift SVN r28580
Before, providing a full SILFunction declaration object with a proper SILType was the only way to link a function. And constructing such a SILFunction declaration by hand using low-level SIL APIs is very annoying and requires a lot of code to be written. This new linkFunction API allows for a lookup using SILDeclRef and essentially performs linking of a SILFunction by its mangled name (assuming this name is unique), which is much easier to invoke. The new API is useful, e.g. when you need to link a well-known function from a standard library.
Swift SVN r26252
We currently do not serialize the body of global addressors. To make
"sil-opt swiftmodule" pass verification, we change the linkage for
the deserialized empty global addressors from public to public external.
rdar://18021024
Swift SVN r22370
Mandatory-inlined (aka transparent functions) are still treated as if they
had the location and scope of the call site. <rdar://problem/14845844>
Support inline scopes once we have an optimizing SIL-based inliner
Patch by Adrian Prantl.
Swift SVN r18835
The deserializer holds a reference to the deserialized SILFunction, which
prevents Dead Function Elimination from erasing them.
We have a tradeoff on how often we should clean up the unused deserialized
SILFunctions. If we clean up at every optimization iteration, we may
end up deserializing the same SILFunction multiple times. For now, we clean
up only after we are done with the optimization iteration.
rdar://17046033
Swift SVN r18697
The on-disk hashtable is moving from clang to llvm. This updates some
consumers for the new path and namespace. I've also shortened the
make_range(data_begin(), data_end()) calls on the hash table to just
use data().
Swift SVN r16537
OnDiskIterableChainedHashTable interface introduced in CFE 206189.
Thanks to Justin for guiding me through this!
The test-failures I was worried about after I originally committed this
turned out to be unrelated.
Swift SVN r16340
This patch adds in the necessary infrastructure for lazily deserializing
witness tables. This is done by following the same approach as the
deserialization/serialization of SILFunction.
Now if one calls SILModule::lookUpWitnessTable and the given witness table is a
definition, the SILModule will attempt to deserialize it from one of the other
modules.
Swift SVN r15403
This fixes a bug where we were deserializing a function with a call to a shared
linkage function. The shared linkage function was never deserialized causing an
assertion to fire due to shared linkage functions always needing a definition.
I am planning on implementing lazy deserialization of vtable functions.
Swift SVN r14581