Skip to content

[semantic-arc] Wire up Parsing/Printing/IRGen/Serialization/Deserialization for copy_value, destroy_value. #5416

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
Oct 23, 2016
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
21 changes: 21 additions & 0 deletions docs/SIL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2246,6 +2246,27 @@ which are not represented as box allocations.
It is produced by SILGen, and is only valid in Raw SIL. It is rewritten as
appropriate by the definitive initialization pass.

mark_uninitialized_behavior
```````````````````````````
::

init-case ::= sil-value sil-apply-substitution-list? '(' sil-value ')' ':' sil-type
set-case ::= sil-value sil-apply-substitution-list? '(' sil-value ')' ':' sil-type
sil-instruction ::= 'mark_uninitialized_behavior' init-case set-case

mark_uninitialized_behavior %init<Subs>(%storage) : $T -> U,
%set<Subs>(%self) : $V -> W

Indicates that a logical property is uninitialized at this point and needs to be
initialized by the end of the function and before any escape point for this
instruction. Assignments to the property trigger the behavior's ``init`` or
``set`` logic based on the logical initialization state of the property.

It is expected that the ``init-case`` is passed some sort of storage and the
``set`` case is passed ``self``.

This is only valid in Raw SIL.

copy_addr
`````````
::
Expand Down
10 changes: 10 additions & 0 deletions include/swift/SIL/SILBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,16 @@ class SILBuilder {
operand, atomicity));
}

CopyValueInst *createCopyValue(SILLocation Loc, SILValue operand) {
return insert(new (F.getModule())
CopyValueInst(getSILDebugLocation(Loc), operand));
}

DestroyValueInst *createDestroyValue(SILLocation Loc, SILValue operand) {
return insert(new (F.getModule())
DestroyValueInst(getSILDebugLocation(Loc), operand));
}

AutoreleaseValueInst *createAutoreleaseValue(SILLocation Loc,
SILValue operand,
Atomicity atomicity) {
Expand Down
27 changes: 21 additions & 6 deletions include/swift/SIL/SILCloner.h
Original file line number Diff line number Diff line change
Expand Up @@ -1131,19 +1131,34 @@ SILCloner<ImplClass>::visitRetainValueInst(RetainValueInst *Inst) {
Inst->getAtomicity()));
}

template<typename ImplClass>
void
SILCloner<ImplClass>::visitReleaseValueInst(ReleaseValueInst *Inst) {
template <typename ImplClass>
void SILCloner<ImplClass>::visitCopyValueInst(CopyValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createCopyValue(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}

template <typename ImplClass>
void SILCloner<ImplClass>::visitReleaseValueInst(ReleaseValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createReleaseValue(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand()),
Inst->getAtomicity()));
}

template<typename ImplClass>
void
SILCloner<ImplClass>::visitAutoreleaseValueInst(AutoreleaseValueInst *Inst) {
template <typename ImplClass>
void SILCloner<ImplClass>::visitDestroyValueInst(DestroyValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(
Inst, getBuilder().createDestroyValue(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}

template <typename ImplClass>
void SILCloner<ImplClass>::visitAutoreleaseValueInst(
AutoreleaseValueInst *Inst) {
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
doPostProcess(Inst,
getBuilder().createAutoreleaseValue(getOpLocation(Inst->getLoc()),
Expand Down
15 changes: 15 additions & 0 deletions include/swift/SIL/SILInstruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -4193,6 +4193,21 @@ class CopyBlockInst :
: UnaryInstructionBase(DebugLoc, operand, operand->getType()) {}
};

class CopyValueInst : public UnaryInstructionBase<ValueKind::CopyValueInst> {
friend class SILBuilder;

CopyValueInst(SILDebugLocation DebugLoc, SILValue operand)
: UnaryInstructionBase(DebugLoc, operand, operand->getType()) {}
};

class DestroyValueInst
: public UnaryInstructionBase<ValueKind::DestroyValueInst> {
friend class SILBuilder;

DestroyValueInst(SILDebugLocation DebugLoc, SILValue operand)
: UnaryInstructionBase(DebugLoc, operand) {}
};

/// Given an object reference, return true iff it is non-nil and refers
/// to a native swift object with strong reference count of 1.
class IsUniqueInst : public UnaryInstructionBase<ValueKind::IsUniqueInst>
Expand Down
2 changes: 2 additions & 0 deletions include/swift/SIL/SILNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ ABSTRACT_VALUE(SILInstruction, ValueBase)
INST(FixLifetimeInst, SILInstruction, fix_lifetime, MayHaveSideEffects, DoesNotRelease)
INST(MarkDependenceInst, SILInstruction, mark_dependence, None, DoesNotRelease)
INST(CopyBlockInst, SILInstruction, copy_block, MayHaveSideEffects, DoesNotRelease)
INST(CopyValueInst, SILInstruction, copy_value, MayHaveSideEffects, DoesNotRelease)
INST(DestroyValueInst, SILInstruction, destroy_value, MayHaveSideEffects, MayRelease)

// IsUnique does not actually write to memory but should be modeled
// as such. Its operand is a pointer to an object reference. The
Expand Down
16 changes: 16 additions & 0 deletions lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,9 @@ class IRGenSILFunction :
void visitLoadWeakInst(LoadWeakInst *i);
void visitStoreWeakInst(StoreWeakInst *i);
void visitRetainValueInst(RetainValueInst *i);
void visitCopyValueInst(CopyValueInst *i);
void visitReleaseValueInst(ReleaseValueInst *i);
void visitDestroyValueInst(DestroyValueInst *i);
void visitAutoreleaseValueInst(AutoreleaseValueInst *i);
void visitSetDeallocatingInst(SetDeallocatingInst *i);
void visitStructInst(StructInst *i);
Expand Down Expand Up @@ -2956,6 +2958,14 @@ void IRGenSILFunction::visitRetainValueInst(swift::RetainValueInst *i) {
out.claimAll();
}

void IRGenSILFunction::visitCopyValueInst(swift::CopyValueInst *i) {
Explosion in = getLoweredExplosion(i->getOperand());
Explosion out;
cast<LoadableTypeInfo>(getTypeInfo(i->getOperand()->getType()))
.copy(*this, in, out, irgen::Atomicity::Atomic);
setLoweredExplosion(i, out);
}

// TODO: Implement this more generally for arbitrary values. Currently the
// SIL verifier restricts it to single-refcounted-pointer types.
void IRGenSILFunction::visitAutoreleaseValueInst(swift::AutoreleaseValueInst *i)
Expand Down Expand Up @@ -3007,6 +3017,12 @@ void IRGenSILFunction::visitReleaseValueInst(swift::ReleaseValueInst *i) {
: irgen::Atomicity::NonAtomic);
}

void IRGenSILFunction::visitDestroyValueInst(swift::DestroyValueInst *i) {
Explosion in = getLoweredExplosion(i->getOperand());
cast<LoadableTypeInfo>(getTypeInfo(i->getOperand()->getType()))
.consume(*this, in, irgen::Atomicity::Atomic);
}

void IRGenSILFunction::visitStructInst(swift::StructInst *i) {
Explosion out;
for (SILValue elt : i->getElements())
Expand Down
5 changes: 4 additions & 1 deletion lib/Parse/ParseSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1927,6 +1927,8 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
UNARY_INSTRUCTION(IsUnique)
UNARY_INSTRUCTION(IsUniqueOrPinned)
UNARY_INSTRUCTION(DestroyAddr)
UNARY_INSTRUCTION(CopyValue)
UNARY_INSTRUCTION(DestroyValue)
UNARY_INSTRUCTION(CondFail)
REFCOUNTING_INSTRUCTION(StrongPin)
REFCOUNTING_INSTRUCTION(StrongRetain)
Expand Down Expand Up @@ -2336,7 +2338,8 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
|| parseValueName(SelfName)
|| P.parseToken(tok::r_paren, diag::expected_tok_in_sil_instr, ")")
|| P.parseToken(tok::colon, diag::expected_tok_in_sil_instr, ":")
|| parseSILType(SetterTy, SetterSig, SetterEnv))
|| parseSILType(SetterTy, SetterSig, SetterEnv)
|| parseSILDebugLocation(InstLoc, B))
return true;

// Resolve the types of the operands.
Expand Down
8 changes: 8 additions & 0 deletions lib/SIL/SILPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,14 @@ class SILPrinter : public SILVisitor<SILPrinter> {
*this << getIDAndType(I->getOperand());
}

void visitCopyValueInst(CopyValueInst *I) {
*this << getIDAndType(I->getOperand());
}

void visitDestroyValueInst(DestroyValueInst *I) {
*this << getIDAndType(I->getOperand());
}

void visitRetainValueInst(RetainValueInst *I) { visitRefCountingInst(I); }

void visitReleaseValueInst(ReleaseValueInst *I) { visitRefCountingInst(I); }
Expand Down
2 changes: 2 additions & 0 deletions lib/SILOptimizer/Utils/SILInliner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
case ValueKind::CopyBlockInst:
case ValueKind::CopyAddrInst:
case ValueKind::RetainValueInst:
case ValueKind::CopyValueInst:
case ValueKind::DeallocBoxInst:
case ValueKind::DeallocExistentialBoxInst:
case ValueKind::DeallocRefInst:
Expand All @@ -337,6 +338,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
case ValueKind::ProjectBoxInst:
case ValueKind::ProjectExistentialBoxInst:
case ValueKind::ReleaseValueInst:
case ValueKind::DestroyValueInst:
case ValueKind::AutoreleaseValueInst:
case ValueKind::DynamicMethodBranchInst:
case ValueKind::DynamicMethodInst:
Expand Down
2 changes: 2 additions & 0 deletions lib/Serialization/DeserializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,8 @@ bool SILDeserializer::readSILInstruction(

UNARY_INSTRUCTION(CondFail)
REFCOUNTING_INSTRUCTION(RetainValue)
UNARY_INSTRUCTION(CopyValue)
UNARY_INSTRUCTION(DestroyValue)
REFCOUNTING_INSTRUCTION(ReleaseValue)
REFCOUNTING_INSTRUCTION(AutoreleaseValue)
REFCOUNTING_INSTRUCTION(SetDeallocating)
Expand Down
2 changes: 2 additions & 0 deletions lib/Serialization/SerializeSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,8 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
}
case ValueKind::CondFailInst:
case ValueKind::RetainValueInst:
case ValueKind::CopyValueInst:
case ValueKind::DestroyValueInst:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please bump the module format version number!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought I did. I guess I did it in an earlier version of the patch. Sorry!

case ValueKind::ReleaseValueInst:
case ValueKind::AutoreleaseValueInst:
case ValueKind::SetDeallocatingInst:
Expand Down
44 changes: 44 additions & 0 deletions test/IRGen/copy_value_destroy_value.sil
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// RUN: %target-swift-frontend -parse-sil -emit-ir %s | %FileCheck %s

// Make sure that we are using type lowering and that we are handling the return
// value correctly.

sil_stage canonical

import Builtin

struct Foo {
var t1 : Builtin.Int32
var c1 : Builtin.NativeObject
var t2 : Builtin.Int32
var c2 : Builtin.NativeObject
var t3 : Builtin.Int32
}

// CHECK: define{{( protected)?}} void @trivial(
// CHECK-NEXT: entry
// CHECK-NEXT: ret void
sil @trivial : $@convention(thin) (Builtin.Int32) -> () {
bb0(%0 : $Builtin.Int32):
%1 = copy_value %0 : $Builtin.Int32
destroy_value %1 : $Builtin.Int32
%2 = tuple()
return %2 : $()
}

// CHECK: define{{( protected)?}} void @non_trivial(
// CHECK: [[GEP1:%.*]] = getelementptr inbounds %V24copy_value_destroy_value3Foo, %V24copy_value_destroy_value3Foo* %0, i32 0, i32 2
// CHECK: [[VAL1:%.*]] = load %swift.refcounted*, %swift.refcounted** [[GEP1]], align 8
// CHECK: [[GEP2:%.*]] = getelementptr inbounds %V24copy_value_destroy_value3Foo, %V24copy_value_destroy_value3Foo* %0, i32 0, i32 5
// CHECK: [[VAL2:%.*]] = load %swift.refcounted*, %swift.refcounted** [[GEP2]], align 8
// CHECK: call void @swift_rt_swift_retain(%swift.refcounted* [[VAL1]])
// CHECK: call void @swift_rt_swift_retain(%swift.refcounted* [[VAL2]])
// CHECK: call void @swift_rt_swift_release(%swift.refcounted* [[VAL1]])
// CHECK: call void @swift_rt_swift_release(%swift.refcounted* [[VAL2]])
sil @non_trivial : $@convention(thin) (Foo) -> () {
bb0(%0 : $Foo):
%1 = copy_value %0 : $Foo
destroy_value %1 : $Foo
%2 = tuple()
return %2 : $()
}
9 changes: 7 additions & 2 deletions test/SIL/Parser/basic.sil
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %target-swift-frontend %s -emit-silgen | %FileCheck %s
// RUN: %target-sil-opt %s | %target-sil-opt | %FileCheck %s

sil_stage raw // CHECK: sil_stage raw

Expand Down Expand Up @@ -1080,10 +1080,15 @@ sil @test_mark_fn_escape : $() -> () {
sil @test_copy_release_value : $(Val) -> (Val) {
bb0(%0 : $Val):
retain_value %0 : $Val
%1 = copy_value %0 : $Val
release_value %0 : $Val
return %0 : $Val
destroy_value %0 : $Val
return %1 : $Val
// CHECK: retain_value [[T0:%.*]] : $Val
// CHECK-NEXT: [[COPY_RESULT:%.*]] = copy_value [[T0]] : $Val
// CHECK-NEXT: release_value [[T0]] : $Val
// CHECK-NEXT: destroy_value [[T0]] : $Val
// CHECK-NEXT: return [[COPY_RESULT]]
}

// CHECK-LABEL: sil @test_autorelease_value
Expand Down
22 changes: 22 additions & 0 deletions test/SIL/Serialization/copy_value_destroy_value.sil
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// First parse this and then emit a *.sib. Then read in the *.sib, then recreate
// RUN: rm -rfv %t
// RUN: mkdir %t
// RUN: %target-sil-opt %s -emit-sib -o %t/tmp.sib -module-name copydestroy_value
// RUN: %target-sil-opt %t/tmp.sib -o %t/tmp.2.sib -module-name copydestroy_value
// RUN: %target-sil-opt %t/tmp.2.sib -module-name copydestroy_value | %FileCheck %s

sil_stage canonical

import Builtin

// CHECK-LABEL: sil @test : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
// CHECK: bb0([[ARG1:%[0-9]+]] : $Builtin.NativeObject):
// CHECK: [[COPY_VALUE_RESULT:%[0-9]+]] = copy_value [[ARG1]] : $Builtin.NativeObject
// CHECK: destroy_value [[ARG1]]
// CHECK: return [[COPY_VALUE_RESULT]]
sil @test : $@convention(thin) (@owned Builtin.NativeObject) -> @owned Builtin.NativeObject {
bb0(%0 : $Builtin.NativeObject):
%1 = copy_value %0 : $Builtin.NativeObject
destroy_value %0 : $Builtin.NativeObject
return %1 : $Builtin.NativeObject
}
3 changes: 2 additions & 1 deletion utils/sil-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@

;; SIL Instructions - Accessing Memory.
`(,(regexp-opt '("load" "store" "assign" "mark_uninitialized"
"mark_uninitialized_behavior"
"mark_function_escape" "copy_addr" "destroy_addr"
"index_addr" "index_raw_pointer" "bind_memory" "to")
'words) . font-lock-keyword-face)
Expand Down Expand Up @@ -106,7 +107,7 @@
`(,(regexp-opt '("retain_value" "release_value" "tuple" "tuple_extract"
"tuple_element_addr" "struct" "struct_extract"
"struct_element_addr" "ref_element_addr"
"autorelease_value")
"autorelease_value" "copy_value" "destroy_value")
'words) . font-lock-keyword-face)
;; Enums. *NOTE* We do not include enum itself here since enum is a
;; swift declaration as well handled at the top.
Expand Down