Skip to content

Commit c504086

Browse files
committed
Revert r21707 "Remove the SIL is_nonnull instruction. It's no longer useful."
We want to be able to work around problems with non-failable Objective-C initializers actually failing, which can happen when the API audit data incorrectly marks an initializer as non-failable. Swift SVN r21711
1 parent eaefb5e commit c504086

File tree

17 files changed

+105
-2
lines changed

17 files changed

+105
-2
lines changed

docs/SIL.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3381,6 +3381,20 @@ Applying the resulting thick function value is equivalent to applying the
33813381
original thin value. The ``thin_to_thick_function`` conversion may be
33823382
eliminated if the context is proven not to be needed.
33833383

3384+
is_nonnull
3385+
``````````
3386+
::
3387+
3388+
sil-instruction ::= 'is_nonnull' sil-operand
3389+
3390+
%1 = is_nonnull %0 : $C
3391+
// %0 must be of reference or function type $C
3392+
// %1 will be of type Builtin.Int1
3393+
3394+
Checks whether a reference type value is null, returning 1 if
3395+
the value is not null, or 0 if it is null. If the value is a function
3396+
type, it checks the function pointer (not the data pointer) for null.
3397+
33843398
Checked Conversions
33853399
~~~~~~~~~~~~~~~~~~~
33863400

include/swift/SIL/PatternMatch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,7 @@ UNARY_OP_MATCH_WITH_ARG_MATCHER(ThickToObjCMetatypeInst)
342342
UNARY_OP_MATCH_WITH_ARG_MATCHER(ObjCToThickMetatypeInst)
343343
UNARY_OP_MATCH_WITH_ARG_MATCHER(ObjCMetatypeToObjectInst)
344344
UNARY_OP_MATCH_WITH_ARG_MATCHER(ObjCExistentialMetatypeToObjectInst)
345+
UNARY_OP_MATCH_WITH_ARG_MATCHER(IsNonnullInst)
345346
UNARY_OP_MATCH_WITH_ARG_MATCHER(RetainValueInst)
346347
UNARY_OP_MATCH_WITH_ARG_MATCHER(ReleaseValueInst)
347348
UNARY_OP_MATCH_WITH_ARG_MATCHER(AutoreleaseValueInst)

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,13 @@ class SILBuilder {
427427
return insert(new (F.getModule()) RefToUnmanagedInst(loc, op, ty));
428428
}
429429

430+
IsNonnullInst *createIsNonnull(SILLocation loc,
431+
SILValue operand) {
432+
return insert(new (F.getModule())
433+
IsNonnullInst(loc, operand,
434+
SILType::getBuiltinIntegerType(1, getASTContext())));
435+
}
436+
430437
UnconditionalCheckedCastInst *createUnconditionalCheckedCast(SILLocation loc,
431438
SILValue op,
432439
SILType destTy) {

include/swift/SIL/SILCloner.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,14 @@ visitObjCToThickMetatypeInst(ObjCToThickMetatypeInst *Inst) {
679679
getOpType(Inst->getType())));
680680
}
681681

682+
template<typename ImplClass>
683+
void
684+
SILCloner<ImplClass>::visitIsNonnullInst(IsNonnullInst *Inst) {
685+
doPostProcess(Inst,
686+
getBuilder().createIsNonnull(getOpLocation(Inst->getLoc()),
687+
getOpValue(Inst->getOperand())));
688+
}
689+
682690
template<typename ImplClass>
683691
void
684692
SILCloner<ImplClass>::visitUnconditionalCheckedCastInst(

include/swift/SIL/SILInstruction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,13 @@ class ObjCProtocolInst : public SILInstruction
13851385
}
13861386
};
13871387

1388+
/// Test that an address or reference type is not null.
1389+
class IsNonnullInst : public UnaryInstructionBase<ValueKind::IsNonnullInst> {
1390+
public:
1391+
IsNonnullInst(SILLocation Loc, SILValue Operand, SILType BoolTy)
1392+
: UnaryInstructionBase(Loc, Operand, BoolTy) {}
1393+
};
1394+
13881395
/// Perform an unconditional checked cast that aborts if the cast fails.
13891396
class UnconditionalCheckedCastInst
13901397
: public UnaryInstructionBase<ValueKind::UnconditionalCheckedCastInst,

include/swift/SIL/SILNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ ABSTRACT_VALUE(SILInstruction, ValueBase)
196196
INST(ObjCExistentialMetatypeToObjectInst, ConversionInst, None)
197197
INST(UnconditionalCheckedCastInst, ConversionInst, None)
198198
VALUE_RANGE(ConversionInst, UpcastInst, UnconditionalCheckedCastInst)
199+
INST(IsNonnullInst, SILInstruction, None)
199200
INST(UnconditionalCheckedCastAddrInst, SILInstruction, MayReadWrite)
200201

201202
// Runtime failure

lib/IRGen/IRGenSIL.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,8 @@ class IRGenSILFunction :
694694
void visitObjCExistentialMetatypeToObjectInst(
695695
ObjCExistentialMetatypeToObjectInst *i);
696696

697+
void visitIsNonnullInst(IsNonnullInst *i);
698+
697699
void visitIndexAddrInst(IndexAddrInst *i);
698700
void visitIndexRawPointerInst(IndexRawPointerInst *i);
699701

@@ -3069,6 +3071,33 @@ void IRGenSILFunction::visitCheckedCastAddrBranchInst(
30693071
getLoweredBB(i->getFailureBB()).bb);
30703072
}
30713073

3074+
void IRGenSILFunction::visitIsNonnullInst(swift::IsNonnullInst *i) {
3075+
// Get the value we're testing, which may be a function, an address or an
3076+
// instance pointer.
3077+
llvm::Value *val;
3078+
const LoweredValue &lv = getLoweredValue(i->getOperand());
3079+
3080+
if (i->getOperand().getType().getSwiftType()->is<SILFunctionType>()) {
3081+
Explosion values = lv.getExplosion(*this);
3082+
val = values.claimNext(); // Function pointer.
3083+
values.claimNext(); // Ignore the data pointer.
3084+
} else if (lv.isAddress()) {
3085+
val = lv.getAddress().getAddress();
3086+
} else {
3087+
Explosion values = lv.getExplosion(*this);
3088+
val = values.claimNext();
3089+
}
3090+
3091+
// Check that the result isn't null.
3092+
auto *valTy = cast<llvm::PointerType>(val->getType());
3093+
llvm::Value *result = Builder.CreateICmp(llvm::CmpInst::ICMP_NE,
3094+
val, llvm::ConstantPointerNull::get(valTy));
3095+
3096+
Explosion out;
3097+
out.add(result);
3098+
setLoweredExplosion(SILValue(i, 0), out);
3099+
}
3100+
30723101
void IRGenSILFunction::visitUpcastInst(swift::UpcastInst *i) {
30733102
auto toTy = getTypeInfo(i->getType()).getStorageType();
30743103

lib/Parse/ParseSIL.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,7 @@ bool SILParser::parseSILOpcode(ValueKind &Opcode, SourceLoc &OpcodeLoc,
11691169
.Case("init_existential_ref", ValueKind::InitExistentialRefInst)
11701170
.Case("inject_enum_addr", ValueKind::InjectEnumAddrInst)
11711171
.Case("integer_literal", ValueKind::IntegerLiteralInst)
1172+
.Case("is_nonnull", ValueKind::IsNonnullInst)
11721173
.Case("function_ref", ValueKind::FunctionRefInst)
11731174
.Case("load", ValueKind::LoadInst)
11741175
.Case("load_weak", ValueKind::LoadWeakInst)
@@ -2504,6 +2505,13 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB) {
25042505
ResultVal = B.createRefElementAddr(InstLoc, Val, Field, ResultTy);
25052506
break;
25062507
}
2508+
case ValueKind::IsNonnullInst: {
2509+
SourceLoc Loc;
2510+
if (parseTypedValueRef(Val, Loc))
2511+
return true;
2512+
ResultVal = B.createIsNonnull(InstLoc, Val);
2513+
break;
2514+
}
25072515
case ValueKind::IndexAddrInst: {
25082516
SILValue IndexVal;
25092517
if (parseTypedValueRef(Val) ||

lib/SIL/SILPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -860,6 +860,10 @@ class SILPrinter : public SILVisitor<SILPrinter> {
860860
<< " : " << CI->getType();
861861
}
862862

863+
void visitIsNonnullInst(IsNonnullInst *I) {
864+
OS << "is_nonnull " << getIDAndType(I->getOperand());
865+
}
866+
863867
void visitRetainValueInst(RetainValueInst *I) {
864868
OS << "retain_value " << getIDAndType(I->getOperand());
865869
}

lib/SIL/Verifier.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,6 +1649,13 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
16491649
}
16501650
}
16511651

1652+
void checkIsNonnullInst(IsNonnullInst *II) {
1653+
// The operand must be a function type or a class type.
1654+
auto OpTy = II->getOperand().getType().getSwiftType();
1655+
require(OpTy->mayHaveSuperclass() || OpTy->is<SILFunctionType>(),
1656+
"is_nonnull operand must be a class or function type");
1657+
}
1658+
16521659
void checkAddressToPointerInst(AddressToPointerInst *AI) {
16531660
require(AI->getOperand().getType().isAddress(),
16541661
"address-to-pointer operand must be an address");

lib/SILAnalysis/ValueTracking.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ static bool isTransitiveEscapeInst(SILInstruction *Inst) {
8787
case ValueKind::InjectEnumAddrInst:
8888
case ValueKind::DeinitExistentialInst:
8989
case ValueKind::UnreachableInst:
90+
case ValueKind::IsNonnullInst:
9091
case ValueKind::CondFailInst:
9192
case ValueKind::DynamicMethodBranchInst:
9293
case ValueKind::ReturnInst:

lib/SILPasses/Utils/SILInliner.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ static InlineCost instructionInlineCost(SILInstruction &I,
365365
case ValueKind::InitExistentialInst:
366366
case ValueKind::InitExistentialRefInst:
367367
case ValueKind::InjectEnumAddrInst:
368+
case ValueKind::IsNonnullInst:
368369
case ValueKind::LoadInst:
369370
case ValueKind::LoadWeakInst:
370371
case ValueKind::OpenExistentialInst:

lib/Serialization/DeserializeSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,7 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
10301030
UNARY_INSTRUCTION(AutoreleaseValue)
10311031
UNARY_INSTRUCTION(DeinitExistential)
10321032
UNARY_INSTRUCTION(DestroyAddr)
1033+
UNARY_INSTRUCTION(IsNonnull)
10331034
UNARY_INSTRUCTION(Load)
10341035
UNARY_INSTRUCTION(Return)
10351036
UNARY_INSTRUCTION(FixLifetime)

lib/Serialization/SerializeSIL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
650650
case ValueKind::DeallocRefInst:
651651
case ValueKind::DeinitExistentialInst:
652652
case ValueKind::DestroyAddrInst:
653+
case ValueKind::IsNonnullInst:
653654
case ValueKind::LoadInst:
654655
case ValueKind::LoadWeakInst:
655656
case ValueKind::MarkUninitializedInst:

test/IRGen/function_types.sil

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,16 @@ entry(%x : $*X):
7070
return %z : $()
7171
}
7272

73+
// CHECK-LABEL: define i1 @test_is_nonnull_function(i8*, %swift.refcounted*) {
74+
// CHECK-NEXT: entry:
75+
// CHECK-NEXT: %2 = icmp ne i8* %0, null
76+
// CHECK-NEXT: ret i1 %2
77+
// CHECK-NEXT: }
78+
79+
sil @test_is_nonnull_function : $@thin (() -> ()) -> Builtin.Int1 {
80+
bb0(%0 : $() -> ()):
81+
%3 = is_nonnull %0 : $() -> ()
82+
return %3 : $Builtin.Int1 // id: %5
83+
}
84+
85+

utils/sil-mode.el

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
"ref_to_raw_pointer" "raw_pointer_to_ref"
109109
"convert_function"
110110
"thick_to_objc_metatype" "objc_to_thick_metatype"
111-
"thin_to_thick_function"
111+
"thin_to_thick_function" "is_nonnull"
112112
"unchecked_ref_bit_cast" "unchecked_trivial_bit_cast")
113113
'words) . font-lock-keyword-face)
114114
;; Checked Conversions

utils/vim/syntax/sil.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ syn keyword swiftKeyword metatype value_metatype existential_metatype skipwhite
3333
syn keyword swiftKeyword retain_value release_value tuple tuple_extract tuple_element_addr struct struct_extract struct_element_addr ref_element_addr skipwhite
3434
syn keyword swiftKeyword init_enum_data_addr unchecked_enum_data unchecked_take_enum_data_addr inject_enum_addr skipwhite
3535
syn keyword swiftKeyword init_existential upcast_existential deinit_existential project_existential open_existential init_existential_ref upcast_existential_ref project_existential_ref open_existential_ref skipwhite
36-
syn keyword swiftKeyword upcast address_to_pointer pointer_to_address unchecked_addr_cast unchecked_ref_cast ref_to_raw_pointer raw_pointer_to_ref convert_function thick_to_objc_metatype objc_to_thick_metatype thin_to_thick_function unchecked_ref_bit_cast unchecked_trivial_bit_cast skipwhite
36+
syn keyword swiftKeyword upcast address_to_pointer pointer_to_address unchecked_addr_cast unchecked_ref_cast ref_to_raw_pointer raw_pointer_to_ref convert_function thick_to_objc_metatype objc_to_thick_metatype thin_to_thick_function is_nonnull unchecked_ref_bit_cast unchecked_trivial_bit_cast skipwhite
3737
syn keyword swiftKeyword unconditional_checked_cast skipwhite
3838
syn keyword swiftKeyword cond_fail skipwhite
3939
syn keyword swiftKeyword unreachable return autorelease_return br cond_br switch_int switch_enum switch_enum_addr dynamic_method_br checked_cast_br skipwhite

0 commit comments

Comments
 (0)