SIL: Add an autorelease_value instruction.

Give us a way to formally represent autoreleases in SIL separate from autoreleased returns, allowing us to lifetime-extend inner pointer parameters the lazy way and hopefully clean up some asmname hacks in the stdlib implementation too.

Swift SVN r16632
This commit is contained in:
Joe Groff
2014-04-21 23:11:38 +00:00
parent c56458d173
commit dcad7fb248
17 changed files with 85 additions and 1 deletions

View File

@@ -409,6 +409,10 @@ public:
return insert(new (F.getModule()) ReleaseValueInst(loc, operand));
}
AutoreleaseValueInst *createAutoreleaseValue(SILLocation loc, SILValue operand) {
return insert(new (F.getModule()) AutoreleaseValueInst(loc, operand));
}
StructInst *createStruct(SILLocation Loc, SILType Ty,
ArrayRef<SILValue> Elements) {
return insert(StructInst::create(Loc, Ty, Elements, F));

View File

@@ -587,6 +587,14 @@ SILCloner<ImplClass>::visitReleaseValueInst(ReleaseValueInst *Inst) {
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitAutoreleaseValueInst(AutoreleaseValueInst *Inst) {
doPostProcess(Inst,
getBuilder().createAutoreleaseValue(getOpLocation(Inst->getLoc()),
getOpValue(Inst->getOperand())));
}
template<typename ImplClass>
void
SILCloner<ImplClass>::visitStructInst(StructInst *Inst) {

View File

@@ -1337,6 +1337,16 @@ public:
: UnaryInstructionBase(loc, operand) {}
};
/// Transfers ownership of a loadable value to the current autorelease pool.
class AutoreleaseValueInst
: public UnaryInstructionBase<ValueKind::AutoreleaseValueInst,
SILInstruction,
/*HasValue*/ false> {
public:
AutoreleaseValueInst(SILLocation loc, SILValue operand)
: UnaryInstructionBase(loc, operand) {}
};
/// TupleInst - Represents a constructed loadable tuple.
class TupleInst : public SILInstruction {
TailAllocatedOperandList<0> Operands;

View File

@@ -140,6 +140,7 @@ ABSTRACT_VALUE(SILInstruction, ValueBase)
// Aggregate Types
INST(RetainValueInst, SILInstruction, MayHaveSideEffects)
INST(ReleaseValueInst, SILInstruction, MayHaveSideEffects)
INST(AutoreleaseValueInst, SILInstruction, MayHaveSideEffects)
INST(TupleInst, SILInstruction, None)
INST(TupleExtractInst, SILInstruction, None)
INST(TupleElementAddrInst, SILInstruction, None)

View File

@@ -40,7 +40,7 @@ const uint16_t VERSION_MAJOR = 0;
/// Serialized module format minor version number.
///
/// When the format changes IN ANY WAY, this number should be incremented.
const uint16_t VERSION_MINOR = 74;
const uint16_t VERSION_MINOR = 77;
using DeclID = Fixnum<31>;
using DeclIDField = BCFixed<31>;

View File

@@ -588,6 +588,7 @@ public:
void visitStoreWeakInst(StoreWeakInst *i);
void visitRetainValueInst(RetainValueInst *i);
void visitReleaseValueInst(ReleaseValueInst *i);
void visitAutoreleaseValueInst(AutoreleaseValueInst *i);
void visitStructInst(StructInst *i);
void visitTupleInst(TupleInst *i);
void visitEnumInst(EnumInst *i);
@@ -2117,6 +2118,22 @@ void IRGenSILFunction::visitRetainValueInst(swift::RetainValueInst *i) {
out.claimAll();
}
// 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)
{
Explosion in = getLoweredExplosion(i->getOperand());
auto val = in.claimNext();
if (val->getType()->isPointerTy())
val = Builder.CreateBitCast(val, IGM.ObjCPtrTy);
else
val = Builder.CreateIntToPtr(val, IGM.ObjCPtrTy);
auto call = Builder.CreateCall(IGM.getObjCAutoreleaseFn(), val);
call->setDoesNotThrow();
}
void IRGenSILFunction::visitReleaseValueInst(swift::ReleaseValueInst *i) {
Explosion in = getLoweredExplosion(i->getOperand());
cast<LoadableTypeInfo>(getTypeInfo(i->getOperand().getType()))

View File

@@ -519,6 +519,8 @@ FUNCTION(ObjCRetain, objc_retain, C_CC,
RETURNS(ObjCPtrTy), ARGS(ObjCPtrTy), ATTRS(NoUnwind))
FUNCTION(ObjCRelease, objc_release, C_CC,
RETURNS(VoidTy), ARGS(ObjCPtrTy), ATTRS(NoUnwind))
FUNCTION(ObjCAutorelease, objc_autorelease, C_CC,
RETURNS(ObjCPtrTy), ARGS(ObjCPtrTy), ATTRS(NoUnwind))
FUNCTION(ObjCRetainAutoreleasedReturnValue,
objc_retainAutoreleasedReturnValue, C_CC,
RETURNS(ObjCPtrTy), ARGS(ObjCPtrTy), ATTRS(NoUnwind))

View File

@@ -994,6 +994,7 @@ bool SILParser::parseSILOpcode(ValueKind &Opcode, SourceLoc &OpcodeLoc,
.Case("apply", ValueKind::ApplyInst)
.Case("assign", ValueKind::AssignInst)
.Case("autorelease_return", ValueKind::AutoreleaseReturnInst)
.Case("autorelease_value", ValueKind::AutoreleaseValueInst)
.Case("br", ValueKind::BranchInst)
.Case("builtin_function_ref", ValueKind::BuiltinFunctionRefInst)
.Case("checked_cast_br", ValueKind::CheckedCastBranchInst)
@@ -1475,6 +1476,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB) {
UNARY_INSTRUCTION(UnownedRetain)
UNARY_INSTRUCTION(UnownedRelease)
UNARY_INSTRUCTION(DestroyAddr)
UNARY_INSTRUCTION(AutoreleaseValue)
UNARY_INSTRUCTION(ReleaseValue)
UNARY_INSTRUCTION(RetainValue)
UNARY_INSTRUCTION(Load)

View File

@@ -801,6 +801,10 @@ public:
OS << "release_value " << getIDAndType(I->getOperand());
}
void visitAutoreleaseValueInst(AutoreleaseValueInst *I) {
OS << "autorelease_value " << getIDAndType(I->getOperand());
}
void visitStructInst(StructInst *SI) {
OS << "struct " << SI->getType() << " (";
interleave(SI->getElements(),

View File

@@ -579,6 +579,14 @@ public:
"Source value should be an object value");
}
void checkAutoreleaseValueInst(ReleaseValueInst *I) {
require(I->getOperand().getType().isObject(),
"Source value should be an object value");
// TODO: This instruction could in principle be generalized.
require(I->getOperand().getType().hasRetainablePointerRepresentation(),
"Source value must be a reference type or optional thereof");
}
void checkCopyBlockInst(CopyBlockInst *I) {
require(I->getOperand().getType().isBlockPointerCompatible(),
"operand of copy_block should be a block");

View File

@@ -64,6 +64,7 @@ static bool isTransitiveEscapeInst(SILInstruction *Inst) {
case ValueKind::DebugValueInst:
case ValueKind::DestroyAddrInst:
case ValueKind::ReleaseValueInst:
case ValueKind::AutoreleaseValueInst:
case ValueKind::FloatLiteralInst:
case ValueKind::FunctionRefInst:
case ValueKind::GlobalAddrInst:

View File

@@ -353,6 +353,7 @@ static InlineCost instructionInlineCost(SILInstruction &I,
case ValueKind::DeinitExistentialInst:
case ValueKind::DestroyAddrInst:
case ValueKind::ReleaseValueInst:
case ValueKind::AutoreleaseValueInst:
case ValueKind::DynamicMethodBranchInst:
case ValueKind::DynamicMethodInst:
case ValueKind::EnumInst:

View File

@@ -1001,6 +1001,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
UNARY_INSTRUCTION(CondFail)
UNARY_INSTRUCTION(RetainValue)
UNARY_INSTRUCTION(ReleaseValue)
UNARY_INSTRUCTION(AutoreleaseValue)
UNARY_INSTRUCTION(DeinitExistential)
UNARY_INSTRUCTION(DestroyAddr)
UNARY_INSTRUCTION(IsNonnull)

View File

@@ -625,6 +625,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
case ValueKind::CondFailInst:
case ValueKind::RetainValueInst:
case ValueKind::ReleaseValueInst:
case ValueKind::AutoreleaseValueInst:
case ValueKind::DeallocStackInst:
case ValueKind::DeallocRefInst:
case ValueKind::DeinitExistentialInst:

View File

@@ -1,6 +1,7 @@
// RUN: %swift -emit-ir -target x86_64-apple-darwin10 %s | FileCheck %s
import Builtin
import Swift
// CHECK: [[OBJCCLASS:%objc_class]] = type
// CHECK: [[OPAQUE:%swift.opaque]] = type opaque
@@ -126,3 +127,22 @@ bb0(%0 : $@thick C.Type):
return %1 : $C
}
// CHECK-LABEL: define %C5class1C* @autorelease(%C5class1C*) {
// CHECK: %1 = bitcast %C5class1C* %0 to %objc_object*
// CHECK: call %objc_object* @objc_autorelease(%objc_object* %1)
// CHECK: ret %C5class1C* %0
sil @autorelease : $@thin (@owned C) -> @autoreleased C {
entry(%c : $C):
autorelease_value %c : $C
return %c : $C
}
// CHECK-LABEL: define i64 @autorelease_optional(i64) {
// CHECK: %1 = inttoptr i64 %0 to %objc_object*
// CHECK: call %objc_object* @objc_autorelease(%objc_object* %1)
// CHECK: ret i64 %0
sil @autorelease_optional : $@thin (@owned C?) -> @autoreleased C? {
entry(%c : $C?):
autorelease_value %c : $C?
return %c : $C?
}

View File

@@ -935,9 +935,11 @@ sil @test_copy_release_value : $(Val) -> (Val) {
bb0(%0 : $Val):
retain_value %0 : $Val
release_value %0 : $Val
autorelease_value %0 : $Val
return %0 : $Val
// CHECK: retain_value [[T0:%.*]] : $Val
// CHECK-NEXT: release_value [[T0]] : $Val
// CHECK-NEXT: autorelease_value [[T0]] : $Val
// CHECK-NEXT: return [[T0]] : $Val
}

View File

@@ -864,9 +864,11 @@ sil @test_copy_release_value : $@thin (Val) -> (Val) {
bb0(%0 : $Val):
retain_value %0 : $Val
release_value %0 : $Val
autorelease_value %0 : $Val
return %0 : $Val
// CHECK: retain_value [[T0:%.*]] : $Val
// CHECK-NEXT: release_value [[T0]] : $Val
// CHECK-NEXT: autorelease_value [[T0]] : $Val
// CHECK-NEXT: return [[T0]] : $Val
}