mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #8090 from shajrawi/ConsumptionKind_UnconditionalCheckedCastValue
Add consumption kind to UnconditionalCheckedCastValueInst
This commit is contained in:
@@ -4489,9 +4489,14 @@ unconditional_checked_cast_value
|
||||
````````````````````````````````
|
||||
::
|
||||
|
||||
sil-instruction ::= 'unconditional_checked_cast_value' sil-operand 'to' sil-type
|
||||
sil-instruction ::= 'unconditional_checked_cast_value'
|
||||
sil-cast-consumption-kind
|
||||
sil-operand 'to' sil-type
|
||||
sil-cast-consumption-kind ::= 'take_always'
|
||||
sil-cast-consumption-kind ::= 'take_on_success'
|
||||
sil-cast-consumption-kind ::= 'copy_on_success'
|
||||
|
||||
%1 = unconditional_checked_cast_value %0 : $A to $B
|
||||
%1 = unconditional_checked_cast_value take_always %0 : $A to $B
|
||||
// $A must not be an address
|
||||
// $B must not be an address
|
||||
// %1 will be of type $B
|
||||
|
||||
@@ -801,10 +801,12 @@ public:
|
||||
}
|
||||
|
||||
UnconditionalCheckedCastValueInst *
|
||||
createUnconditionalCheckedCastValue(SILLocation Loc, SILValue op,
|
||||
SILType destTy) {
|
||||
createUnconditionalCheckedCastValue(SILLocation Loc,
|
||||
CastConsumptionKind consumption,
|
||||
SILValue op, SILType destTy) {
|
||||
return insert(UnconditionalCheckedCastValueInst::create(
|
||||
getSILDebugLocation(Loc), op, destTy, F, OpenedArchetypes));
|
||||
getSILDebugLocation(Loc), consumption, op, destTy, F,
|
||||
OpenedArchetypes));
|
||||
}
|
||||
|
||||
RetainValueInst *createRetainValue(SILLocation Loc, SILValue operand,
|
||||
|
||||
@@ -1165,7 +1165,7 @@ void SILCloner<ImplClass>::visitUnconditionalCheckedCastValueInst(
|
||||
SILType OpType = getOpType(Inst->getType());
|
||||
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
|
||||
doPostProcess(Inst, getBuilder().createUnconditionalCheckedCastValue(
|
||||
OpLoc, OpValue, OpType));
|
||||
OpLoc, Inst->getConsumptionKind(), OpValue, OpType));
|
||||
}
|
||||
|
||||
template <typename ImplClass>
|
||||
|
||||
@@ -2862,16 +2862,24 @@ class UnconditionalCheckedCastValueInst final
|
||||
ValueKind::UnconditionalCheckedCastValueInst,
|
||||
UnconditionalCheckedCastValueInst, ConversionInst, true> {
|
||||
friend SILBuilder;
|
||||
CastConsumptionKind ConsumptionKind;
|
||||
|
||||
UnconditionalCheckedCastValueInst(SILDebugLocation DebugLoc, SILValue Operand,
|
||||
UnconditionalCheckedCastValueInst(SILDebugLocation DebugLoc,
|
||||
CastConsumptionKind consumption,
|
||||
SILValue Operand,
|
||||
ArrayRef<SILValue> TypeDependentOperands,
|
||||
SILType DestTy)
|
||||
: UnaryInstructionWithTypeDependentOperandsBase(
|
||||
DebugLoc, Operand, TypeDependentOperands, DestTy) {}
|
||||
DebugLoc, Operand, TypeDependentOperands, DestTy),
|
||||
ConsumptionKind(consumption) {}
|
||||
|
||||
static UnconditionalCheckedCastValueInst *
|
||||
create(SILDebugLocation DebugLoc, SILValue Operand, SILType DestTy,
|
||||
SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes);
|
||||
create(SILDebugLocation DebugLoc, CastConsumptionKind consumption,
|
||||
SILValue Operand, SILType DestTy, SILFunction &F,
|
||||
SILOpenedArchetypesState &OpenedArchetypes);
|
||||
|
||||
public:
|
||||
CastConsumptionKind getConsumptionKind() const { return ConsumptionKind; }
|
||||
};
|
||||
|
||||
/// StructInst - Represents a constructed loadable struct.
|
||||
|
||||
@@ -2481,9 +2481,34 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
|
||||
break;
|
||||
}
|
||||
|
||||
case ValueKind::UnconditionalCheckedCastValueInst: {
|
||||
CastConsumptionKind consumptionKind;
|
||||
Identifier consumptionKindToken;
|
||||
SourceLoc consumptionKindLoc;
|
||||
SILType ty;
|
||||
SILValue destVal;
|
||||
Identifier toToken;
|
||||
SourceLoc toLoc;
|
||||
if (parseSILIdentifier(consumptionKindToken, consumptionKindLoc,
|
||||
diag::expected_tok_in_sil_instr,
|
||||
"cast consumption kind") ||
|
||||
parseCastConsumptionKind(consumptionKindToken, consumptionKindLoc,
|
||||
consumptionKind))
|
||||
return true;
|
||||
|
||||
if (parseTypedValueRef(Val, B) || parseVerbatim("to") || parseSILType(ty))
|
||||
return true;
|
||||
|
||||
if (parseSILDebugLocation(InstLoc, B))
|
||||
return true;
|
||||
|
||||
ResultVal = B.createUnconditionalCheckedCastValue(InstLoc, consumptionKind,
|
||||
Val, ty);
|
||||
break;
|
||||
}
|
||||
|
||||
// Checked Conversion instructions.
|
||||
case ValueKind::UnconditionalCheckedCastInst:
|
||||
case ValueKind::UnconditionalCheckedCastValueInst:
|
||||
case ValueKind::CheckedCastValueBranchInst:
|
||||
case ValueKind::CheckedCastBranchInst: {
|
||||
SILType ty;
|
||||
@@ -2507,11 +2532,6 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
|
||||
return true;
|
||||
ResultVal = B.createUnconditionalCheckedCast(InstLoc, Val, ty);
|
||||
break;
|
||||
} else if (Opcode == ValueKind::UnconditionalCheckedCastValueInst) {
|
||||
if (parseSILDebugLocation(InstLoc, B))
|
||||
return true;
|
||||
ResultVal = B.createUnconditionalCheckedCastValue(InstLoc, Val, ty);
|
||||
break;
|
||||
}
|
||||
// The conditional cast still needs its branch destinations.
|
||||
Identifier successBBName, failureBBName;
|
||||
|
||||
@@ -1775,7 +1775,8 @@ UnconditionalCheckedCastInst *UnconditionalCheckedCastInst::create(
|
||||
}
|
||||
|
||||
UnconditionalCheckedCastValueInst *UnconditionalCheckedCastValueInst::create(
|
||||
SILDebugLocation DebugLoc, SILValue Operand, SILType DestTy, SILFunction &F,
|
||||
SILDebugLocation DebugLoc, CastConsumptionKind consumption,
|
||||
SILValue Operand, SILType DestTy, SILFunction &F,
|
||||
SILOpenedArchetypesState &OpenedArchetypes) {
|
||||
SILModule &Mod = F.getModule();
|
||||
SmallVector<SILValue, 8> TypeDependentOperands;
|
||||
@@ -1786,7 +1787,7 @@ UnconditionalCheckedCastValueInst *UnconditionalCheckedCastValueInst::create(
|
||||
void *Buffer =
|
||||
Mod.allocateInst(size, alignof(UnconditionalCheckedCastValueInst));
|
||||
return ::new (Buffer) UnconditionalCheckedCastValueInst(
|
||||
DebugLoc, Operand, TypeDependentOperands, DestTy);
|
||||
DebugLoc, consumption, Operand, TypeDependentOperands, DestTy);
|
||||
}
|
||||
|
||||
CheckedCastBranchInst *CheckedCastBranchInst::create(
|
||||
|
||||
@@ -1224,7 +1224,8 @@ public:
|
||||
|
||||
void visitUnconditionalCheckedCastValueInst(
|
||||
UnconditionalCheckedCastValueInst *CI) {
|
||||
*this << getIDAndType(CI->getOperand()) << " to " << CI->getType();
|
||||
*this << getCastConsumptionKindName(CI->getConsumptionKind()) << ' '
|
||||
<< getIDAndType(CI->getOperand()) << " to " << CI->getType();
|
||||
}
|
||||
|
||||
void visitCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CI) {
|
||||
|
||||
@@ -546,9 +546,10 @@ ManagedValue SILGenBuilder::createEnum(SILLocation loc, ManagedValue payload,
|
||||
}
|
||||
|
||||
ManagedValue SILGenBuilder::createUnconditionalCheckedCastValue(
|
||||
SILLocation loc, ManagedValue operand, SILType type) {
|
||||
SILLocation loc, CastConsumptionKind consumption, ManagedValue operand,
|
||||
SILType type) {
|
||||
SILValue result = SILBuilder::createUnconditionalCheckedCastValue(
|
||||
loc, operand.forward(SGF), type);
|
||||
loc, consumption, operand.forward(SGF), type);
|
||||
return SGF.emitManagedRValueWithCleanup(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -224,9 +224,10 @@ public:
|
||||
SGFContext context, std::function<void(SILValue)> rvalueEmitter);
|
||||
|
||||
using SILBuilder::createUnconditionalCheckedCastValue;
|
||||
ManagedValue createUnconditionalCheckedCastValue(SILLocation loc,
|
||||
ManagedValue operand,
|
||||
SILType type);
|
||||
ManagedValue
|
||||
createUnconditionalCheckedCastValue(SILLocation loc,
|
||||
CastConsumptionKind consumption,
|
||||
ManagedValue operand, SILType type);
|
||||
using SILBuilder::createUnconditionalCheckedCast;
|
||||
ManagedValue createUnconditionalCheckedCast(SILLocation loc,
|
||||
ManagedValue operand,
|
||||
|
||||
@@ -102,7 +102,8 @@ namespace {
|
||||
ManagedValue result;
|
||||
if (Strategy == CastStrategy::Address) {
|
||||
result = SGF.B.createUnconditionalCheckedCastValue(
|
||||
Loc, operand, origTargetTL.getLoweredType());
|
||||
Loc, CastConsumptionKind::TakeAlways, operand,
|
||||
origTargetTL.getLoweredType());
|
||||
} else {
|
||||
result = SGF.B.createUnconditionalCheckedCast(
|
||||
Loc, operand, origTargetTL.getLoweredType());
|
||||
@@ -388,7 +389,8 @@ namespace {
|
||||
SILValue resultScalar;
|
||||
if (Strategy == CastStrategy::Address) {
|
||||
resultScalar = SGF.B.createUnconditionalCheckedCastValue(
|
||||
Loc, operand.forward(SGF), origTargetTL.getLoweredType());
|
||||
Loc, CastConsumptionKind::TakeAlways, operand.forward(SGF),
|
||||
origTargetTL.getLoweredType());
|
||||
} else {
|
||||
resultScalar = SGF.B.createUnconditionalCheckedCast(
|
||||
Loc, operand.forward(SGF), origTargetTL.getLoweredType());
|
||||
|
||||
@@ -2046,7 +2046,7 @@ SILInstruction *CastOptimizer::simplifyCheckedCastValueBranchInst(
|
||||
|
||||
if (!CastedValue)
|
||||
CastedValue = Builder.createUnconditionalCheckedCastValue(
|
||||
Loc, Op, LoweredTargetType);
|
||||
Loc, CastConsumptionKind::TakeAlways, Op, LoweredTargetType);
|
||||
} else {
|
||||
CastedValue = SILUndef::get(LoweredTargetType, Mod);
|
||||
}
|
||||
|
||||
@@ -1930,10 +1930,12 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
|
||||
break;
|
||||
}
|
||||
case ValueKind::UnconditionalCheckedCastValueInst: {
|
||||
CastConsumptionKind consumption = getCastConsumptionKind(Attr);
|
||||
SILValue Val = getLocalValue(
|
||||
ValID, getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2));
|
||||
SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
|
||||
ResultVal = Builder.createUnconditionalCheckedCastValue(Loc, Val, Ty);
|
||||
ResultVal =
|
||||
Builder.createUnconditionalCheckedCastValue(Loc, consumption, Val, Ty);
|
||||
break;
|
||||
}
|
||||
case ValueKind::UnconditionalCheckedCastAddrInst:
|
||||
|
||||
@@ -1313,7 +1313,8 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
|
||||
auto CI = cast<UnconditionalCheckedCastValueInst>(&SI);
|
||||
SILInstCastLayout::emitRecord(
|
||||
Out, ScratchRecord, SILAbbrCodes[SILInstCastLayout::Code],
|
||||
(unsigned)SI.getKind(), /*attr*/ 0,
|
||||
(unsigned)SI.getKind(),
|
||||
toStableCastConsumptionKind(CI->getConsumptionKind()),
|
||||
S.addTypeRef(CI->getType().getSwiftRValueType()),
|
||||
(unsigned)CI->getType().getCategory(),
|
||||
S.addTypeRef(CI->getOperand()->getType().getSwiftRValueType()),
|
||||
|
||||
@@ -16,11 +16,11 @@ struct S : Foo {
|
||||
|
||||
// CHECK-LABEL: sil @castOpaque : $@convention(thin) (Int) -> () {
|
||||
// CHECK: bb0([[ARG:%.*]] : $Int):
|
||||
// CHECK: unconditional_checked_cast_value [[ARG]] : $Int to $Foo
|
||||
// CHECK: unconditional_checked_cast_value take_always [[ARG]] : $Int to $Foo
|
||||
// CHECK-LABEL: } // end sil function 'castOpaque'
|
||||
sil @castOpaque : $@convention(thin) (Int) -> () {
|
||||
bb0(%0 : $Int):
|
||||
%c = unconditional_checked_cast_value %0 : $Int to $Foo
|
||||
%c = unconditional_checked_cast_value take_always %0 : $Int to $Foo
|
||||
%t = tuple ()
|
||||
return %t : $()
|
||||
}
|
||||
|
||||
@@ -22,11 +22,11 @@ struct S : Foo {
|
||||
|
||||
// CHECK-LABEL: sil @castOpaque : $@convention(thin) (Int) -> () {
|
||||
// CHECK: bb0([[ARG:%.*]] : $Int):
|
||||
// CHECK: unconditional_checked_cast_value [[ARG]] : $Int to $Foo
|
||||
// CHECK: unconditional_checked_cast_value take_always [[ARG]] : $Int to $Foo
|
||||
// CHECK-LABEL: } // end sil function 'castOpaque'
|
||||
sil @castOpaque : $@convention(thin) (Int) -> () {
|
||||
bb0(%0 : $Int):
|
||||
%c = unconditional_checked_cast_value %0 : $Int to $Foo
|
||||
%c = unconditional_checked_cast_value take_always %0 : $Int to $Foo
|
||||
%t = tuple ()
|
||||
return %t : $()
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@ import Builtin
|
||||
|
||||
sil @unconditional_checked_cast_value_test : $@convention(thin) <T> (Builtin.Int32) -> @out T {
|
||||
bb0(%0 : @trivial $Builtin.Int32):
|
||||
%1 = unconditional_checked_cast_value %0 : $Builtin.Int32 to $T
|
||||
%1 = unconditional_checked_cast_value take_always %0 : $Builtin.Int32 to $T
|
||||
return %1 : $T
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ func s160_______callAnyArg() {
|
||||
// CHECK: [[INT_TYPE:%.*]] = metatype $@thin Int.Type
|
||||
// CHECK: [[INT_LIT:%.*]] = integer_literal $Builtin.Int2048, 42
|
||||
// CHECK: [[INT_ARG:%.*]] = apply %{{.*}}([[INT_LIT]], [[INT_TYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
|
||||
// CHECK: [[INT_CAST:%.*]] = unconditional_checked_cast_value [[INT_ARG]] : $Int to $T
|
||||
// CHECK: [[INT_CAST:%.*]] = unconditional_checked_cast_value take_always [[INT_ARG]] : $Int to $T
|
||||
// CHECK: [[CAST_BORROW:%.*]] = begin_borrow [[INT_CAST]] : $T
|
||||
// CHECK: [[RETURN_VAL:%.*]] = copy_value [[CAST_BORROW]] : $T
|
||||
// CHECK: end_borrow [[CAST_BORROW]] from [[INT_CAST]] : $T, $T
|
||||
@@ -276,7 +276,7 @@ func s170____force_convert<T>() -> T {
|
||||
// CHECK: bb0:
|
||||
// CHECK: [[INT_LIT:%.*]] = integer_literal $Builtin.Int2048, 42
|
||||
// CHECK: [[INT_ARG:%.*]] = apply %{{.*}}([[INT_LIT]], [[INT_TYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
|
||||
// CHECK: [[INT_CAST:%.*]] = unconditional_checked_cast_value [[INT_ARG]] : $Int to $Foo
|
||||
// CHECK: [[INT_CAST:%.*]] = unconditional_checked_cast_value take_always [[INT_ARG]] : $Int to $Foo
|
||||
// CHECK: return [[INT_CAST]] : $Foo
|
||||
// CHECK-LABEL: } // end sil function '_T020opaque_values_silgen21s180_______return_fooAA3Foo_pyF'
|
||||
func s180_______return_foo() -> Foo {
|
||||
|
||||
Reference in New Issue
Block a user