This is the lifetime ending variant of fix_lifetime. It is a lie to the
ownership verifier that a value is being consumed along a path. Its intention is
to be used to allow for the static verification of ownership in deallocating
deinits which for compatibility with objective-c have weird ownership behavior.
See the commit merged with this commit for more information.
Also take the opportunity to simplify the code and tighten the assertions.
The commit does not contain a test-case, because it is kind of difficult to provide a reduced one.
The idea of the fix stems from @slavapestov. I just provided minor improvements and tested it on a very big test-case to see that it fixes the bug.
Once we move to a copy-on-write implementation of existential value buffers we
can no longer consume or destroy values of an opened existential unless the
buffer is uniquely owned.
Therefore we need to track the allowed operation on opened values.
Add qualifiers "mutable_access" and "immutable_access" to open_existential_addr
instructions to indicate the allowed access to the opened value.
Once we move to a copy-on-write implementation, an "open_existential_addr
mutable_access" instruction will ensure unique ownership of the value buffer.
SubstitutionList is going to be a more compact representation of
a SubstitutionMap, suitable for inline allocation inside another
object.
For now, it's just a typedef for ArrayRef<Substitution>.
A new SubstitutionMap::getProtocolSubstitutions() method handles
the case where we construct a trivial SubstitutionMap to replace
the protocol Self type with a concrete type.
When substituting one opened existential archetype for another,
use the form of Type::subst() that takes two callbacks instead of
building a SubstitutionMap. SubstitutionMaps are intended to be
used with keys that either come from a GenericSignature or a
GenericEnvironment, so using them to replace opened archetypes
doesn't fit the conceptual model we're going for.
The reason why I am introducing special instructions is so I can maintain the
qualified ownership API wedge in between qualified SIL and the rest of the ARC
instructions that are pervasively used in the compiler.
These instructions in the future /could/ be extended to just take @sil_unmanaged
operands directly, but I want to maintain flexibility to take regular
non-trivial operands in the short term.
rdar://29791263
Not sure why but this was another "toxic utility method".
Most of the usages fell into one of three categories:
- The base value was always non-null, so we could just call
getCanonicalType() instead, making intent more explicit
- The result was being compared for equality, so we could
skip canonicalization and call isEqual() instead, removing
some boilerplate
- Utterly insane code that made no sense
There were only a couple of legitimate uses, and even there
open-coding the conditional null check made the code clearer.
Also while I'm at it, make the SIL open archetypes tracker
more typesafe by passing around ArchetypeType * instead of
Type and CanType.
We preserve the current behavior of assuming Any ownership always and use
default arguments to hide this change most of the time. There are asserts now in
the SILBasicBlock::{create,replace,insert}{PHI,Function}Argument to ensure that
the people can only create SILFunctionArguments in entry blocks and
SILPHIArguments in non-entry blocks. This will ensure that the code in tree
maintains the API distinction even if we are not using the full distinction in
between the two.
Once the verifier is finished being upstreamed, I am going to audit the
createPHIArgument cases for the proper ownership. This is b/c I will be able to
use the verifier to properly debug the code. At that point, I will also start
serializing/printing/parsing the ownershipkind of SILPHIArguments, but lets take
things one step at a time and move incrementally.
In the process, I also discovered a CSE bug. I am not sure how it ever worked.
Basically we replace an argument with a new argument type but return the uses of
the old argument to refer to the old argument instead of a new argument.
rdar://29671437
This was in the first high level ARC instruction proposal, but I have not needed
it until now. The use case for this is to ahandle strong_retain_unowned (which
takes in an unowned value, asserts it is still alive, performs a strong_retain,
and returns the @owned value). This @owned value needs a destroy_value.
rdar://29671437
This simplifies the SILType substitution APIs and brings them in line with Doug and Slava's refactorings to improve AST-level type substitution. NFC intended.
This was made redundant by typed boxes, and the type operand was already removed from textual SIL, but the field was never removed from the instruction's in memory representation. It becomes wrong in the face of compound boxes with layout.
Before this commit all code relating to handling arguments in SILBasicBlock had
somewhere in the name BB. This is redundant given that the class's name is
already SILBasicBlock. This commit drops those names.
Some examples:
getBBArg() => getArgument()
BBArgList => ArgumentList
bbarg_begin() => args_begin()
This eliminates all inline creation of SILBasicBlock via placement new.
There are a few reasons to do this:
1. A SILBasicBlock is always created with a parent function. This commit
formalizes this into the SILBasicBlock API by only allowing for SILFunctions to
create SILBasicBlocks. This is implemented via the type system by making all
SILBasicBlock constructors private. Since SILFunction is a friend of
SILBasicBlock, SILFunction can still create a SILBasicBlock without issue.
2. Since all SILBasicBlocks will be created in only a few functions, it becomes
very easy to determine using instruments the amount of memory being allocated
for SILBasicBlocks by simply inverting the call tree in Allocations.
With LTO+PGO, normal inlining can occur if profitable so there shouldn't be
overhead that we care about in shipping compilers.
Today, loads and stores are treated as having @unowned(unsafe) ownership
semantics. This leaves the user to specify ownership changes on the loaded or
stored value independently of the load/store by inserting ARC operations. With
the change to Semantic SIL, this will no longer be true. Instead loads, stores
have ownership semantics that one must reason about such as copy, take, and
trivial.
This change moves us closer to that world by eliminating the default
OwnershipQualification argument from create{Load,Store}. This means that the
compiler developer cannot ignore reasoning about the ownership semantics of the
memory operation that they are creating.
Operationally, this is a NFC change since I have just gone through the compiler
and updated all places where we create loads, stores to pass in the former
default argument ({Load,Store}OwnershipQualifier::Unqualified), to
SILBuilder::create{Load,Store}(...). For now, one can just do that in situations
where one needs to create loads/stores, but over time, I am going to tighten the
semantics up via the verifier.
rdar://28685236
This is a cleanup for SILParsing/Printing. I verified that everything was
spelled correctly by taking the current parsing switch moving that into a file,
regenerating it using the .def file and then diffed them. The diff was the same.
rdar://28685236
It's the same thing as for alloc_ref: the optional [tail_elems ...] attribute specify the tail elements to allocate.
For details see docs/SIL.rst
This feature is needed so that we can allocate a MangedBuffer with alloc_ref_dynamic.
The ManagedBuffer.create() function uses the dynamic self type to create the buffer instance.
The new instructions are: ref_tail_addr, tail_addr and a new attribute [ tail_elems ] for alloc_ref.
For details see docs/SIL.rst
As these new instructions are not generated so far, this is a NFC.
The new instructions are: ref_tail_addr, tail_addr and a new attribute [ tail_elems ] for alloc_ref.
For details see docs/SIL.rst
As these new instructions are not generated so far, this is a NFC.
This establishes a real def-use relation from the self-parameter to any instruction which uses the dynamic-self type.
This is an addition to what was already done for opened archetypes.
The biggest part of this commit is to rename "OpenedArchetypeOperands" to "TypeDependentOperands" as this name is now more appropriate.
Other than that the change includes:
*) type-dependent operands are now printed after a SIL instruction in a comment as "type-defs:" (for debugging)
*) FuncationSignatureOpts doesn't need to explicitly check if a function doesn't bind dynamic self to remove a dead self metadata argument
*) the check if a function binds dynamic self (used in the inliner) is much simpler now
*) also collect type-dependent operands for ApplyInstBase::SubstCalleeType and not only in the substitution list
*) with this SILInstruction::mayHaveOpenedArchetypeOperands (used in CSE) is not needed anymore and removed
*) add type dependent operands to dynamic_method instruction
Regarding the generated code it should be a NFC.
It is important to call doPreProcess to correctly setup the available opened archetypes which were referenced from the original instruction being copied.
This fixes a concrete bug in LoopRotate optimization and potential bugs related to cloning.
rdar://27659420