The bridging function that we are calling here takes in the value to be bridged
at +0. We were storing that value via a normal store. This looks like a double
consume since we were destroying the value later. Now we use a store_borrow.
rdar://29791263
Except GenericEnvironment.h, because you can't meaningfully use a
GenericEnvironment without its signature. Lots less depends on
GenericSignature.h now. NFC
This replaces the '[volatile]' flag. Now, class_method and
super_method are only used for vtable dispatch.
The witness_method instruction is still overloaded for use
with both ObjC protocol requirements and Swift protocol
requirements; the next step is to make it only mean the
latter, also using objc_method for ObjC protocol calls.
Use the ManagedValue forms of the SILInstruction constructors
where possible. This ensures that after emitting an instruction
such as an upcast, we rewrite the value's cleanup to destroy
the new value, and not the old value. This is important because
the ownership verifier asserts that instructions dominated by
a destroy cannot use the destroyed value.
Should be NFC, since the ownership verifier is off by default
for now.
Remove the cast consumption kind from all unconditional casts. It
doesn't make sense for unconditional casts, complicates SIL ownership,
and wasn't fully supported for all variants. Copies should be
explicit.
These instructions have the same semantics as the *ExistentialAddr instructions
but operate directly on the existential value, not its address.
This is in preparation for adding ExistentialBoxValue instructions.
The previous name would cause impossible confusion with "opaque existentials"
and "opaque existential boxes".
Previously we were storing a pointer to the non-yet blockified function and not
cleaning it up. This was safe since we were performing a copy_block on the block
and destroying the SSA value of the non-yet blockified function. This looks like
a double consume to the ownership verifier. To fix this, I changed the bridging
code to use a new entrypoint for storing on SILGenBuilder that just does the
right thing by forwarding the cleanup on the SSA value and transfering it to the
address. This means the address will be destroyed instead of the SSA value,
yielding proper ownership.
rdar://31880847
When I originally implemented this, I did not understand why an unowned(unsafe)
value was unsafe. I thought it was unsafe since the value was not meant to be
paired with (which is why I used the unmanaged_retain_value). Instead it just
means that we perform an unconditional copy without checking if the unowned
value is actually live. In contrast, an unowned(safe) value, we use
copy_unowned_value which performs an assert that the unowned value is still
alive before copying.
From a non-semantic sil perspective, since I still was retaining the value
properly, there was not a bug by using the unmanaged_retain_value instruction.
rdar://31880847
The main thing here is that we create a cleanup that inserts the
end_borrow_argument. Once I merge end_borrow with end_borrow_argument, there
will only be one cleanup.
rdar://31880847
Use 'hasAssociatedValues' instead of computing and discarding the
interface type of an enum element decl. This change has specifically not
been made in conditions that use the presence or absence of the
interface type, only conditions that depend on the presence or absence
of associated values in the enum element decl.
Till now createApply, createTryApply, createPartialApply were taking some arguments like SubstCalleeType or ResultType. But these arguments are redundant and can be easily derived from other arguments of these functions. There is no need to put the burden of their computation on the clients of these APIs.
The removal of these redundant parameters simplifies the APIs and reduces the possibility of providing mismatched types by clients, which often happened in the past.
The new API is broken. Popping a generic context frees all
dependent type lowerings, so this function returns a pointer
to freed memory.
This reverts commit 24dfae0716.
This commit does a few things:
1. It uses SwitchEnumBuilder so we are not re-inventing any wheels.
2. Instead of hacking around not putting in a destroy for .None on the fail
pass, just *do the right thing* and recognize that we have a binary case enum
and in such a case, just emit code for the other case rather than use a default
case (meaning no cleanup on .none).
rdar://31145255
The reason that this is being done is that:
1. SILGenFunction is passed around all throughout SILGen, including in between
APIs some of which call the SILGenFunction variable SGF and others that call it
gen.
2. Thus when one is debugging code in SILGen, one wastes time figuring out what
the variable name of SILGenFunction is in the current frame.
I did not do this by hand. I did this by:
1. Grepping for "SILGenFunction &gen".
2. By hand inspecting that the match was truly a SILGenFunction &gen site.
3. If so, use libclang tooling to rename the variable to SGF.
So I did not update any use sites.
This is a closure based API for creating switches that obey ownership
convensions. The way you use it with objects is as follows:
SwitchEnumBuilder S(...);
S.addCase(Decl, Block, [](ManagedValue Arg) -> void {
...
});
S.addCase(Decl, Block, [](ManagedValue Arg) -> void {
...
});
S.addDefaultCase(Block, [](ManagedValue Arg) -> void {
...
});
std::move(S).emit();
What is important is that it sets up the switch_enum destination blocks with the
proper cleanups for code emitted into the destination block and also provides
the default error with the passed in value with the appropriate cleanups.
It does not handle exits from the switch_enum on purpose since diamond
switch_enum APIs form a subset of APIs. It also expects the closure to create
terminators if appropriate.
In the switch_enum_addr case you have to do a bit more work, but it is still a
nicer API than doing it by hand as we do today.
rdar://29791263
Previously, we would put a destroy_value directly on the value that we tried to
cast. Since checked_cast_br is consuming, this would cause the destroy_value on
the failure path to be flagged as a double consume.
This commit causes SILGen to emit the value consumed by checked_cast_br as an
@owned argument to the failure BB, allowing semantic arc rules to be respected.
As an additional benefit, I also upgraded the ownership_model_eliminator test to
use semantic sil verification.
One issue that did come up though is that I was unable to use the new code in
all locations in the compiler. Specifically, there is one location in
SILGenPattern that uses argument unforwarding. I am going to need to undo
argument unforwarding in SILGenPattern in order to completely eliminate the old
code path.
This is in preparation for removing the +0 self hack.
This commit in more detail does the following:
1. It adds Formal Evaluation Scopes to certain places where the scopes were
missing. Specifically:
a. The SILGenLValue cases are places where we are invoking accessors. In each
one of these cases, we had a formal evaluation scope in the accessor
itself, but we did not have a scope that closed over the base access and
the accessor access. The base access is a formal evaluation in the sense
that just like with inout bases, we must create a new reference to the
base and re-destroy the base in a chain of accesses. This is to ensure
that we do not extend the lifetime of the base inappropriately.
b. The SILGenPoly case is a place where we have never properly placed a
Formal Evaluation Scope and have completely been relying on the +0 self
hack to make sure that archetype callees are properly destroyed
immediately after a +0 call.
2. It changes all of the places in SILGen that emit self to using formal access
cleanups instead of normal cleanups.
rdar://29791263