introduce a common superclass, SILNode.
This is in preparation for allowing instructions to have multiple
results. It is also a somewhat more elegant representation for
instructions that have zero results. Instructions that are known
to have exactly one result inherit from a class, SingleValueInstruction,
that subclasses both ValueBase and SILInstruction. Some care must be
taken when working with SILNode pointers and testing for equality;
please see the comment on SILNode for more information.
A number of SIL passes needed to be updated in order to handle this
new distinction between SIL values and SIL instructions.
Note that the SIL parser is now stricter about not trying to assign
a result value from an instruction (like 'return' or 'strong_retain')
that does not produce any.
We compile with a pedantic warning that complains about these things,
and the massive flood of warnings is actually causing problems for the
build infrastructure.
Looping over all users and returning the only user of a specific type is a
common pattern in the compiler. This method just allows for the loop to be
eliminated.
There are a few different use cases here:
1. In Raw SIL, no return folding may not have been run yet implying that a call
to a no-return function /can/ have arbitrary control flow after it (consider
mandatory inlined functions). We need to recognize that the region of code that
is strictly post dominated by the no-return function is "transitively
unreachable" and thus leaking is ok from that point. *Footnote 1*.
2. In Canonical and Raw SIL, we must recognize that unreachables and no-return
functions constitute places where we are allowed to leak.
rdar://29791263
----
*Footnote 1*: The reason why this is done is since we want to emit unreachable
code diagnostics when we run no-return folding. By leaving in the relevant code,
we have preserved all of the SILLocations on that code allowing us to create
really nice diagnostics.
Most of this involved sprinkling ValueOwnershipKind::Owned in many places. In
some of these places, I am sure I was too cavalier and I expect some of them to
be trivial. The verifier will help me to track those down.
On the other hand, I do expect there to be some places where we are willing to
accept guaranteed+trivial or owned+trivial. In those cases, I am going to
provide an aggregate ValueOwnershipKind that will then tell SILArgument that it
should disambiguate using the type. This will eliminate the ackwardness from
such code.
I am going to use a verifier to fix such cases.
This commit also begins the serialization of ValueOwnershipKind of arguments,
but does not implement parsing of value ownership kinds. That and undef are the
last places that we still use ValueOwnershipKind::Any.
rdar://29791263
This commit includes the dataflow verifier and plugs in the use checker into the
dataflow verifier.
Some specific checks in the use checker need revision, but I for today
this is good enough. As I go through SILGen I am going to fix them.
rdar://29671437
I fixed a few things. Now I am finally hitting cases where we have
guaranteed/owned arguments, so I really need to do the SILGen work. But this was
a good first step.
rdar://29671437
The implementation will rely on a SILVisitor to ensure that we properly handle
all relevant cases. Right now, there are only stubs and we assert in all of
them.
rdar://29671437
These APIs work just like getParentBB does, namely they attempt to cast
self to either SILInstruction/SILArgument and if the instance is one of
those classes, using the APIs on said classes to get the relevant
Function or Module. If the dynamic casts fail, then nullptr is returned.
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.