Skip to content

SIL instructions for SSA existentials. #11034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 18, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 34 additions & 17 deletions docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3828,9 +3828,9 @@ container may use one of several representations:
before IR generation.
The following instructions manipulate "loadable" opaque existential containers:

* `init_existential_opaque`_
* `open_existential_opaque`_
* `deinit_existential_opaque`_
* `init_existential_value`_
* `open_existential_value`_
* `deinit_existential_value`_

- **Class existential containers**: If a protocol type is constrained by one or
more class protocols, then the existential container for that type is
Expand Down Expand Up @@ -3859,6 +3859,7 @@ container may use one of several representations:
* `alloc_existential_box`_
* `project_existential_box`_
* `open_existential_box`_
* `open_existential_box_value`_
* `dealloc_existential_box`_

Some existential types may additionally support specialized representations
Expand Down Expand Up @@ -3904,14 +3905,14 @@ initialized existential container can be destroyed with ``destroy_addr`` as
usual. It is undefined behavior to ``destroy_addr`` a partially-initialized
existential container.

init_existential_opaque
```````````````````````
init_existential_value
``````````````````````
::

sil-instruction ::= 'init_existential_opaque' sil-operand ':' sil-type ','
sil-instruction ::= 'init_existential_value' sil-operand ':' sil-type ','
sil-type

%1 = init_existential_opaque %0 : $L' : $C, $P
%1 = init_existential_value %0 : $L' : $C, $P
// %0 must be of loadable type $L', lowered from AST type $L, conforming to
// protocol(s) $P
// %1 will be of type $P
Expand All @@ -3935,20 +3936,20 @@ existential containers that have been partially initialized by
``init_existential_addr`` but haven't had their contained value initialized.
A fully initialized existential must be destroyed with ``destroy_addr``.

deinit_existential_opaque
`````````````````````````
deinit_existential_value
````````````````````````
::

sil-instruction ::= 'deinit_existential_opaque' sil-operand
sil-instruction ::= 'deinit_existential_value' sil-operand

deinit_existential_opaque %0 : $P
deinit_existential_value %0 : $P
// %0 must be of a $P opaque type for non-class protocol or protocol
// composition type P

Undoes the partial initialization performed by
``init_existential_opaque``. ``deinit_existential_opaque`` is only valid for
``init_existential_value``. ``deinit_existential_value`` is only valid for
existential containers that have been partially initialized by
``init_existential_opaque`` but haven't had their contained value initialized.
``init_existential_value`` but haven't had their contained value initialized.
A fully initialized existential must be destroyed with ``destroy_value``.

open_existential_addr
Expand Down Expand Up @@ -3976,13 +3977,13 @@ access constraint: The returned address can either allow ``mutable_access`` or
(e.g ``destroy_addr`` or ``copy_addr [take]``) or mutate the value at the
address if they have ``mutable_access``.

open_existential_opaque
```````````````````````
open_existential_value
``````````````````````
::

sil-instruction ::= 'open_existential_opaque' sil-operand 'to' sil-type
sil-instruction ::= 'open_existential_value' sil-operand 'to' sil-type

%1 = open_existential_opaque %0 : $P to $@opened P
%1 = open_existential_value %0 : $P to $@opened P
// %0 must be of a $P type for non-class protocol or protocol composition
// type P
// $@opened P must be a unique archetype that refers to an opened
Expand Down Expand Up @@ -4118,6 +4119,22 @@ the owning box and the enclosing function; in order to "open" a boxed
existential that has directly adopted a class reference, temporary scratch
space may need to have been allocated.

open_existential_box_value
``````````````````````````
::

sil-instruction ::= 'open_existential_box_value' sil-operand 'to' sil-type

%1 = open_existential_box_value %0 : $P to $@opened P
// %0 must be a value of boxed protocol or protocol composition type $P
// %@opened P must be a unique archetype that refers to an opened
// existential type P
// %1 will be of type $@opened P

Projects the value inside a boxed existential container, and uses the enclosed
type and protocol conformance metadata to bind the opened archetype ``$@opened
P``.

dealloc_existential_box
```````````````````````
::
Expand Down
6 changes: 3 additions & 3 deletions include/swift/SIL/PatternMatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,12 +366,12 @@ UNARY_OP_MATCH_WITH_ARG_MATCHER(SuperMethodInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(DynamicMethodInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(OpenExistentialAddrInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(OpenExistentialRefInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(OpenExistentialOpaqueInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(OpenExistentialValueInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(InitExistentialAddrInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(InitExistentialOpaqueInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(InitExistentialValueInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(InitExistentialRefInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(DeinitExistentialAddrInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(DeinitExistentialOpaqueInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(DeinitExistentialValueInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(ProjectBlockStorageInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(StrongRetainInst)
UNARY_OP_MATCH_WITH_ARG_MATCHER(StrongReleaseInst)
Expand Down
25 changes: 17 additions & 8 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1188,10 +1188,10 @@ class SILBuilder {
return I;
}

OpenExistentialOpaqueInst *createOpenExistentialOpaque(SILLocation Loc,
OpenExistentialValueInst *createOpenExistentialValue(SILLocation Loc,
SILValue Operand,
SILType SelfTy) {
auto *I = insert(new (F.getModule()) OpenExistentialOpaqueInst(
auto *I = insert(new (F.getModule()) OpenExistentialValueInst(
getSILDebugLocation(Loc), Operand, SelfTy));
if (OpenedArchetypesTracker)
OpenedArchetypesTracker->registerOpenedArchetypes(I);
Expand Down Expand Up @@ -1226,6 +1226,15 @@ class SILBuilder {
return I;
}

OpenExistentialBoxValueInst *
createOpenExistentialBoxValue(SILLocation Loc, SILValue Operand, SILType Ty) {
auto *I = insert(new (F.getModule()) OpenExistentialBoxValueInst(
getSILDebugLocation(Loc), Operand, Ty));
if (OpenedArchetypesTracker)
OpenedArchetypesTracker->registerOpenedArchetypes(I);
return I;
}

InitExistentialAddrInst *
createInitExistentialAddr(SILLocation Loc, SILValue Existential,
CanType FormalConcreteType,
Expand All @@ -1236,11 +1245,11 @@ class SILBuilder {
LoweredConcreteType, Conformances, &F, OpenedArchetypes));
}

InitExistentialOpaqueInst *
createInitExistentialOpaque(SILLocation Loc, SILType ExistentialType,
InitExistentialValueInst *
createInitExistentialValue(SILLocation Loc, SILType ExistentialType,
CanType FormalConcreteType, SILValue Concrete,
ArrayRef<ProtocolConformanceRef> Conformances) {
return insert(InitExistentialOpaqueInst::create(
return insert(InitExistentialValueInst::create(
getSILDebugLocation(Loc), ExistentialType, FormalConcreteType, Concrete,
Conformances, &F, OpenedArchetypes));
}
Expand Down Expand Up @@ -1269,9 +1278,9 @@ class SILBuilder {
getSILDebugLocation(Loc), Existential));
}

DeinitExistentialOpaqueInst *
createDeinitExistentialOpaque(SILLocation Loc, SILValue Existential) {
return insert(new (F.getModule()) DeinitExistentialOpaqueInst(
DeinitExistentialValueInst *
createDeinitExistentialValue(SILLocation Loc, SILValue Existential) {
return insert(new (F.getModule()) DeinitExistentialValueInst(
getSILDebugLocation(Loc), Existential));
}

Expand Down
36 changes: 27 additions & 9 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -1586,8 +1586,8 @@ SILCloner<ImplClass>::visitOpenExistentialAddrInst(OpenExistentialAddrInst *Inst
}

template <typename ImplClass>
void SILCloner<ImplClass>::visitOpenExistentialOpaqueInst(
OpenExistentialOpaqueInst *Inst) {
void SILCloner<ImplClass>::visitOpenExistentialValueInst(
OpenExistentialValueInst *Inst) {
// Create a new archetype for this opened existential type.
auto archetypeTy =
Inst->getType().getSwiftRValueType()->castTo<ArchetypeType>();
Expand All @@ -1596,7 +1596,7 @@ void SILCloner<ImplClass>::visitOpenExistentialOpaqueInst(
ArchetypeType::getOpened(archetypeTy->getOpenedExistentialType()));

getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst, getBuilder().createOpenExistentialOpaque(
doPostProcess(Inst, getBuilder().createOpenExistentialValue(
getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
Expand Down Expand Up @@ -1671,6 +1671,24 @@ visitOpenExistentialBoxInst(OpenExistentialBoxInst *Inst) {
getOpType(Inst->getType())));
}

template<typename ImplClass>
void
SILCloner<ImplClass>::
visitOpenExistentialBoxValueInst(OpenExistentialBoxValueInst *Inst) {
// Create a new archetype for this opened existential type.
auto archetypeTy
= Inst->getType().getSwiftRValueType()->castTo<ArchetypeType>();
registerOpenedExistentialRemapping(
archetypeTy,
ArchetypeType::getOpened(archetypeTy->getOpenedExistentialType()));

getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createOpenExistentialBoxValue(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
getOpType(Inst->getType())));
}

template<typename ImplClass>
void
SILCloner<ImplClass>::visitInitExistentialAddrInst(InitExistentialAddrInst *Inst) {
Expand All @@ -1689,16 +1707,16 @@ SILCloner<ImplClass>::visitInitExistentialAddrInst(InitExistentialAddrInst *Inst
}

template <typename ImplClass>
void SILCloner<ImplClass>::visitInitExistentialOpaqueInst(
InitExistentialOpaqueInst *Inst) {
void SILCloner<ImplClass>::visitInitExistentialValueInst(
InitExistentialValueInst *Inst) {
CanType origFormalType = Inst->getFormalConcreteType();

auto conformances = getOpConformances(origFormalType,
Inst->getConformances());

getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createInitExistentialOpaque(
getBuilder().createInitExistentialValue(
getOpLocation(Inst->getLoc()), getOpType(Inst->getType()),
getOpASTType(origFormalType),
getOpValue(Inst->getOperand()), conformances));
Expand Down Expand Up @@ -1747,11 +1765,11 @@ SILCloner<ImplClass>::visitDeinitExistentialAddrInst(DeinitExistentialAddrInst *
}

template <typename ImplClass>
void SILCloner<ImplClass>::visitDeinitExistentialOpaqueInst(
DeinitExistentialOpaqueInst *Inst) {
void SILCloner<ImplClass>::visitDeinitExistentialValueInst(
DeinitExistentialValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(
Inst, getBuilder().createDeinitExistentialOpaque(
Inst, getBuilder().createDeinitExistentialValue(
getOpLocation(Inst->getLoc()), getOpValue(Inst->getOperand())));
}

Expand Down
31 changes: 21 additions & 10 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -4700,11 +4700,11 @@ class OpenExistentialAddrInst
/// Given an opaque value referring to an existential, "opens" the
/// existential by returning a pointer to a fresh archetype T, which also
/// captures the (dynamic) conformances.
class OpenExistentialOpaqueInst
: public UnaryInstructionBase<ValueKind::OpenExistentialOpaqueInst> {
class OpenExistentialValueInst
: public UnaryInstructionBase<ValueKind::OpenExistentialValueInst> {
friend SILBuilder;

OpenExistentialOpaqueInst(SILDebugLocation DebugLoc, SILValue Operand,
OpenExistentialValueInst(SILDebugLocation DebugLoc, SILValue Operand,
SILType SelfTy);
};

Expand Down Expand Up @@ -4745,6 +4745,17 @@ class OpenExistentialBoxInst
SILType ty);
};

/// Given a boxed existential container, "opens" the existential by returning a
/// fresh archetype T, which also captures the (dynamic) conformances.
class OpenExistentialBoxValueInst
: public UnaryInstructionBase<ValueKind::OpenExistentialBoxValueInst>
{
friend SILBuilder;

OpenExistentialBoxValueInst(SILDebugLocation DebugLoc, SILValue operand,
SILType ty);
};

/// Given an address to an uninitialized buffer of
/// a protocol type, initializes its existential container to contain a concrete
/// value of the given type, and returns the address of the uninitialized
Expand Down Expand Up @@ -4794,24 +4805,24 @@ class InitExistentialAddrInst final
/// initializes its existential container to contain a concrete
/// value of the given type, and returns the uninitialized
/// concrete value inside the existential container.
class InitExistentialOpaqueInst final
class InitExistentialValueInst final
: public UnaryInstructionWithTypeDependentOperandsBase<
ValueKind::InitExistentialOpaqueInst, InitExistentialOpaqueInst,
ValueKind::InitExistentialValueInst, InitExistentialValueInst,
SILInstruction, true> {
friend SILBuilder;

CanType ConcreteType;
ArrayRef<ProtocolConformanceRef> Conformances;

InitExistentialOpaqueInst(SILDebugLocation DebugLoc, SILType ExistentialType,
InitExistentialValueInst(SILDebugLocation DebugLoc, SILType ExistentialType,
CanType FormalConcreteType, SILValue Instance,
ArrayRef<SILValue> TypeDependentOperands,
ArrayRef<ProtocolConformanceRef> Conformances)
: UnaryInstructionWithTypeDependentOperandsBase(
DebugLoc, Instance, TypeDependentOperands, ExistentialType),
ConcreteType(FormalConcreteType), Conformances(Conformances) {}

static InitExistentialOpaqueInst *
static InitExistentialValueInst *
create(SILDebugLocation DebugLoc, SILType ExistentialType,
CanType ConcreteType, SILValue Instance,
ArrayRef<ProtocolConformanceRef> Conformances, SILFunction *Parent,
Expand Down Expand Up @@ -4928,12 +4939,12 @@ class DeinitExistentialAddrInst
: UnaryInstructionBase(DebugLoc, Existential) {}
};

class DeinitExistentialOpaqueInst
: public UnaryInstructionBase<ValueKind::DeinitExistentialOpaqueInst,
class DeinitExistentialValueInst
: public UnaryInstructionBase<ValueKind::DeinitExistentialValueInst,
SILInstruction, /*HAS_RESULT*/ false> {
friend SILBuilder;

DeinitExistentialOpaqueInst(SILDebugLocation DebugLoc, SILValue Existential)
DeinitExistentialValueInst(SILDebugLocation DebugLoc, SILValue Existential)
: UnaryInstructionBase(DebugLoc, Existential) {}
};

Expand Down
7 changes: 4 additions & 3 deletions include/swift/SIL/SILNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -233,18 +233,19 @@ ABSTRACT_VALUE(SILInstruction, ValueBase)

// Protocol and Protocol Composition Types
INST(InitExistentialAddrInst, SILInstruction, init_existential_addr, MayWrite, DoesNotRelease)
INST(InitExistentialOpaqueInst, SILInstruction, init_existential_opaque, MayWrite, DoesNotRelease)
INST(InitExistentialValueInst, SILInstruction, init_existential_value, MayWrite, DoesNotRelease)
INST(DeinitExistentialAddrInst, SILInstruction, deinit_existential_addr, MayHaveSideEffects,
DoesNotRelease)
INST(DeinitExistentialOpaqueInst, SILInstruction, deinit_existential_opaque, MayHaveSideEffects,
INST(DeinitExistentialValueInst, SILInstruction, deinit_existential_value, MayHaveSideEffects,
DoesNotRelease)
INST(OpenExistentialAddrInst, SILInstruction, open_existential_addr, MayRead, DoesNotRelease)
INST(InitExistentialRefInst, SILInstruction, init_existential_ref, None, DoesNotRelease)
INST(OpenExistentialRefInst, SILInstruction, open_existential_ref, None, DoesNotRelease)
INST(InitExistentialMetatypeInst, SILInstruction, init_existential_metatype, None, DoesNotRelease)
INST(OpenExistentialMetatypeInst, SILInstruction, open_existential_metatype, None, DoesNotRelease)
INST(OpenExistentialBoxInst, SILInstruction, open_existential_box, MayRead, DoesNotRelease)
INST(OpenExistentialOpaqueInst, SILInstruction, open_existential_opaque, MayRead, DoesNotRelease)
INST(OpenExistentialValueInst, SILInstruction, open_existential_value, MayRead, DoesNotRelease)
INST(OpenExistentialBoxValueInst, SILInstruction, open_existential_box_value, MayRead, DoesNotRelease)

// Blocks
INST(ProjectBlockStorageInst, SILInstruction, project_block_storage, None, DoesNotRelease)
Expand Down
Loading