Skip to content

Commit d1dae72

Browse files
author
Joe Shajrawi
authored
Merge pull request #7700 from shajrawi/unconditional_checked_cast
Add support for unconditional checked cast instruction for opaque value types + SILGen support for it
2 parents 4696f27 + ec1e3ee commit d1dae72

20 files changed

+158
-15
lines changed

docs/SIL.rst

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4429,7 +4429,7 @@ Checked Conversions
44294429

44304430
Some user-level cast operations can fail and thus require runtime checking.
44314431

4432-
The `unconditional_checked_cast_addr`_ and `unconditional_checked_cast`_
4432+
The `unconditional_checked_cast_addr`_, `unconditional_checked_cast_opaque`_ and `unconditional_checked_cast`_
44334433
instructions performs an unconditional checked cast; it is a runtime failure
44344434
if the cast fails. The `checked_cast_addr_br`_ and `checked_cast_br`_
44354435
terminator instruction performs a conditional checked cast; it branches to one
@@ -4468,6 +4468,20 @@ unconditional_checked_cast_addr
44684468
Performs a checked indirect conversion, causing a runtime failure if the
44694469
conversion fails.
44704470

4471+
unconditional_checked_cast_opaque
4472+
`````````````````````````````````
4473+
::
4474+
4475+
sil-instruction ::= 'unconditional_checked_cast_opaque' sil-operand 'to' sil-type
4476+
4477+
%1 = unconditional_checked_cast_opaque %0 : $A to $B
4478+
// $A must be not be an address
4479+
// $B must be an opaque value
4480+
// %1 will be of type $B
4481+
4482+
Performs a checked conversion, causing a runtime failure if the
4483+
conversion fails.
4484+
44714485
Runtime Failures
44724486
~~~~~~~~~~~~~~~~
44734487

include/swift/SIL/SILBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,13 @@ class SILBuilder {
797797
targetType));
798798
}
799799

800+
UnconditionalCheckedCastOpaqueInst *
801+
createUnconditionalCheckedCastOpaque(SILLocation Loc, SILValue op,
802+
SILType destTy) {
803+
return insert(UnconditionalCheckedCastOpaqueInst::create(
804+
getSILDebugLocation(Loc), op, destTy, F, OpenedArchetypes));
805+
}
806+
800807
RetainValueInst *createRetainValue(SILLocation Loc, SILValue operand,
801808
Atomicity atomicity) {
802809
assert(isParsing || F.hasUnqualifiedOwnership());

include/swift/SIL/SILCloner.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,10 +1149,20 @@ SILCloner<ImplClass>::visitUnconditionalCheckedCastAddrInst(
11491149
SrcValue, SrcType,
11501150
DestValue, TargetType));
11511151
}
1152-
1153-
template<typename ImplClass>
1154-
void
1155-
SILCloner<ImplClass>::visitRetainValueInst(RetainValueInst *Inst) {
1152+
1153+
template <typename ImplClass>
1154+
void SILCloner<ImplClass>::visitUnconditionalCheckedCastOpaqueInst(
1155+
UnconditionalCheckedCastOpaqueInst *Inst) {
1156+
SILLocation OpLoc = getOpLocation(Inst->getLoc());
1157+
SILValue OpValue = getOpValue(Inst->getOperand());
1158+
SILType OpType = getOpType(Inst->getType());
1159+
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1160+
doPostProcess(Inst, getBuilder().createUnconditionalCheckedCastOpaque(
1161+
OpLoc, OpValue, OpType));
1162+
}
1163+
1164+
template <typename ImplClass>
1165+
void SILCloner<ImplClass>::visitRetainValueInst(RetainValueInst *Inst) {
11561166
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
11571167
doPostProcess(Inst,
11581168
getBuilder().createRetainValue(getOpLocation(Inst->getLoc()),

include/swift/SIL/SILInstruction.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2836,6 +2836,26 @@ class UnconditionalCheckedCastAddrInst : public SILInstruction
28362836
}
28372837
};
28382838

2839+
/// Perform an unconditional checked cast that aborts if the cast fails.
2840+
/// The result of the checked cast is left in the destination.
2841+
class UnconditionalCheckedCastOpaqueInst final
2842+
: public UnaryInstructionWithTypeDependentOperandsBase<
2843+
ValueKind::UnconditionalCheckedCastOpaqueInst,
2844+
UnconditionalCheckedCastOpaqueInst, ConversionInst, true> {
2845+
friend SILBuilder;
2846+
2847+
UnconditionalCheckedCastOpaqueInst(SILDebugLocation DebugLoc,
2848+
SILValue Operand,
2849+
ArrayRef<SILValue> TypeDependentOperands,
2850+
SILType DestTy)
2851+
: UnaryInstructionWithTypeDependentOperandsBase(
2852+
DebugLoc, Operand, TypeDependentOperands, DestTy) {}
2853+
2854+
static UnconditionalCheckedCastOpaqueInst *
2855+
create(SILDebugLocation DebugLoc, SILValue Operand, SILType DestTy,
2856+
SILFunction &F, SILOpenedArchetypesState &OpenedArchetypes);
2857+
};
2858+
28392859
/// StructInst - Represents a constructed loadable struct.
28402860
class StructInst : public SILInstruction {
28412861
friend SILBuilder;

include/swift/SIL/SILNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ ABSTRACT_VALUE(SILInstruction, ValueBase)
266266
INST(ObjCMetatypeToObjectInst, ConversionInst, objc_metatype_to_object, None, DoesNotRelease)
267267
INST(ObjCExistentialMetatypeToObjectInst, ConversionInst, objc_existential_metatype_to_object, None,
268268
DoesNotRelease)
269+
INST(UnconditionalCheckedCastOpaqueInst, ConversionInst, unconditional_checked_cast_opaque, None, DoesNotRelease)
269270
INST(UnconditionalCheckedCastInst, ConversionInst, unconditional_checked_cast, None, DoesNotRelease)
270271
VALUE_RANGE(ConversionInst, UpcastInst, UnconditionalCheckedCastInst)
271272
INST(IsNonnullInst, SILInstruction, is_nonnull, None, DoesNotRelease)

lib/IRGen/IRGenSIL.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,8 @@ class IRGenSILFunction :
965965
void visitObjCToThickMetatypeInst(ObjCToThickMetatypeInst *i);
966966
void visitUnconditionalCheckedCastInst(UnconditionalCheckedCastInst *i);
967967
void visitUnconditionalCheckedCastAddrInst(UnconditionalCheckedCastAddrInst *i);
968+
void visitUnconditionalCheckedCastOpaqueInst(
969+
UnconditionalCheckedCastOpaqueInst *i);
968970
void visitObjCMetatypeToObjectInst(ObjCMetatypeToObjectInst *i);
969971
void visitObjCExistentialMetatypeToObjectInst(
970972
ObjCExistentialMetatypeToObjectInst *i);
@@ -4276,6 +4278,11 @@ void IRGenSILFunction::visitUnconditionalCheckedCastAddrInst(
42764278
i->getConsumptionKind(), CheckedCastMode::Unconditional);
42774279
}
42784280

4281+
void IRGenSILFunction::visitUnconditionalCheckedCastOpaqueInst(
4282+
swift::UnconditionalCheckedCastOpaqueInst *i) {
4283+
llvm_unreachable("unsupported instruction during IRGen");
4284+
}
4285+
42794286
void IRGenSILFunction::visitCheckedCastBranchInst(
42804287
swift::CheckedCastBranchInst *i) {
42814288
SILType destTy = i->getCastType();

lib/Parse/ParseSIL.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2448,6 +2448,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
24482448

24492449
// Checked Conversion instructions.
24502450
case ValueKind::UnconditionalCheckedCastInst:
2451+
case ValueKind::UnconditionalCheckedCastOpaqueInst:
24512452
case ValueKind::CheckedCastBranchInst: {
24522453
SILType ty;
24532454
SILValue destVal;
@@ -2470,7 +2471,12 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
24702471
return true;
24712472
ResultVal = B.createUnconditionalCheckedCast(InstLoc, Val, ty);
24722473
break;
2473-
}
2474+
} else if (Opcode == ValueKind::UnconditionalCheckedCastOpaqueInst) {
2475+
if (parseSILDebugLocation(InstLoc, B))
2476+
return true;
2477+
ResultVal = B.createUnconditionalCheckedCastOpaque(InstLoc, Val, ty);
2478+
break;
2479+
}
24742480
// The conditional cast still needs its branch destinations.
24752481
Identifier successBBName, failureBBName;
24762482
SourceLoc successBBLoc, failureBBLoc;

lib/SIL/InstructionUtils.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static bool isRCIdentityPreservingCast(ValueKind Kind) {
6767
case ValueKind::UncheckedRefCastInst:
6868
case ValueKind::UncheckedRefCastAddrInst:
6969
case ValueKind::UnconditionalCheckedCastInst:
70+
case ValueKind::UnconditionalCheckedCastOpaqueInst:
7071
case ValueKind::RefToBridgeObjectInst:
7172
case ValueKind::BridgeObjectToRefInst:
7273
return true;
@@ -363,6 +364,7 @@ void ConformanceCollector::collect(swift::SILInstruction *I) {
363364
case ValueKind::AllocRefDynamicInst:
364365
case ValueKind::MetatypeInst:
365366
case ValueKind::UnconditionalCheckedCastInst:
367+
case ValueKind::UnconditionalCheckedCastOpaqueInst:
366368
scanType(I->getType().getSwiftRValueType());
367369
break;
368370
case ValueKind::AllocStackInst: {

lib/SIL/SILInstructions.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,21 @@ UnconditionalCheckedCastInst *UnconditionalCheckedCastInst::create(
17721772
TypeDependentOperands, DestTy);
17731773
}
17741774

1775+
UnconditionalCheckedCastOpaqueInst *UnconditionalCheckedCastOpaqueInst::create(
1776+
SILDebugLocation DebugLoc, SILValue Operand, SILType DestTy, SILFunction &F,
1777+
SILOpenedArchetypesState &OpenedArchetypes) {
1778+
SILModule &Mod = F.getModule();
1779+
SmallVector<SILValue, 8> TypeDependentOperands;
1780+
collectTypeDependentOperands(TypeDependentOperands, OpenedArchetypes, F,
1781+
DestTy.getSwiftRValueType());
1782+
unsigned size =
1783+
totalSizeToAlloc<swift::Operand>(1 + TypeDependentOperands.size());
1784+
void *Buffer =
1785+
Mod.allocateInst(size, alignof(UnconditionalCheckedCastOpaqueInst));
1786+
return ::new (Buffer) UnconditionalCheckedCastOpaqueInst(
1787+
DebugLoc, Operand, TypeDependentOperands, DestTy);
1788+
}
1789+
17751790
CheckedCastBranchInst *CheckedCastBranchInst::create(
17761791
SILDebugLocation DebugLoc, bool IsExact, SILValue Operand, SILType DestTy,
17771792
SILBasicBlock *SuccessBB, SILBasicBlock *FailureBB, SILFunction &F,

lib/SIL/SILOwnershipVerifier.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ static bool isOwnershipForwardingValueKind(ValueKind K) {
193193
case ValueKind::RefToBridgeObjectInst:
194194
case ValueKind::BridgeObjectToRefInst:
195195
case ValueKind::UnconditionalCheckedCastInst:
196+
case ValueKind::UnconditionalCheckedCastOpaqueInst:
196197
case ValueKind::TupleExtractInst:
197198
case ValueKind::StructExtractInst:
198199
case ValueKind::UncheckedEnumDataInst:
@@ -563,6 +564,7 @@ FORWARD_ANY_OWNERSHIP_INST(ConvertFunction)
563564
FORWARD_ANY_OWNERSHIP_INST(RefToBridgeObject)
564565
FORWARD_ANY_OWNERSHIP_INST(BridgeObjectToRef)
565566
FORWARD_ANY_OWNERSHIP_INST(UnconditionalCheckedCast)
567+
FORWARD_ANY_OWNERSHIP_INST(UnconditionalCheckedCastOpaque)
566568
FORWARD_ANY_OWNERSHIP_INST(MarkUninitialized)
567569
FORWARD_ANY_OWNERSHIP_INST(UncheckedEnumData)
568570
#undef FORWARD_ANY_OWNERSHIP_INST

lib/SIL/SILPrinter.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1216,7 +1216,12 @@ class SILPrinter : public SILVisitor<SILPrinter> {
12161216
<< " to " << CI->getTargetType() << " in "
12171217
<< getIDAndType(CI->getDest());
12181218
}
1219-
1219+
1220+
void visitUnconditionalCheckedCastOpaqueInst(
1221+
UnconditionalCheckedCastOpaqueInst *CI) {
1222+
*this << getIDAndType(CI->getOperand()) << " to " << CI->getType();
1223+
}
1224+
12201225
void visitCheckedCastAddrBranchInst(CheckedCastAddrBranchInst *CI) {
12211226
*this << getCastConsumptionKindName(CI->getConsumptionKind()) << ' '
12221227
<< CI->getSourceType() << " in " << getIDAndType(CI->getSrc())

lib/SIL/SILValue.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ FORWARDING_OWNERSHIP_INST(Struct)
417417
FORWARDING_OWNERSHIP_INST(Tuple)
418418
FORWARDING_OWNERSHIP_INST(UncheckedRefCast)
419419
FORWARDING_OWNERSHIP_INST(UnconditionalCheckedCast)
420+
FORWARDING_OWNERSHIP_INST(UnconditionalCheckedCastOpaque)
420421
FORWARDING_OWNERSHIP_INST(Upcast)
421422
FORWARDING_OWNERSHIP_INST(MarkUninitialized)
422423
FORWARDING_OWNERSHIP_INST(UncheckedEnumData)

lib/SIL/SILVerifier.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2509,6 +2509,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
25092509
verifyOpenedArchetype(CI, CI->getType().getSwiftRValueType());
25102510
}
25112511

2512+
void checkUnconditionalCheckedCastOpaqueInst(
2513+
UnconditionalCheckedCastOpaqueInst *CI) {
2514+
verifyOpenedArchetype(CI, CI->getType().getSwiftRValueType());
2515+
}
2516+
25122517
/// Verify if a given type is or contains an opened archetype or dynamic self.
25132518
/// If this is the case, verify that the provided instruction has a type
25142519
/// dependent operand for it.

lib/SILGen/SILGenDynamicCast.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,15 @@ namespace {
5656
SGFContext ctx;
5757

5858
std::unique_ptr<TemporaryInitialization> temporary;
59-
if (isOperandIndirect()) {
59+
if (isOperandIndirect() && SGF.silConv.useLoweredAddresses()) {
6060
temporary = SGF.emitTemporary(Loc, origSourceTL);
6161
ctx = SGFContext(temporary.get());
6262
}
6363

6464
auto result = SGF.emitRValueAsOrig(operand, mostGeneral,
6565
origSourceTL, ctx);
6666

67-
if (isOperandIndirect()) {
67+
if (isOperandIndirect() && SGF.silConv.useLoweredAddresses()) {
6868
// Force the result into the temporary if it's not already there.
6969
if (!result.isInContext()) {
7070
result.forwardInto(SGF, Loc, temporary->getAddress());
@@ -87,7 +87,8 @@ namespace {
8787

8888
// If we're using checked_cast_addr, take the operand (which
8989
// should be an address) and build into the destination buffer.
90-
if (Strategy == CastStrategy::Address) {
90+
if (Strategy == CastStrategy::Address &&
91+
SGF.silConv.useLoweredAddresses()) {
9192
SILValue resultBuffer =
9293
createAbstractResultBuffer(hasAbstraction, origTargetTL, ctx);
9394
SGF.B.createUnconditionalCheckedCastAddr(Loc,
@@ -99,9 +100,15 @@ namespace {
99100
abstraction, origTargetTL, ctx));
100101
}
101102

102-
SILValue resultScalar =
103-
SGF.B.createUnconditionalCheckedCast(Loc, operand.forward(SGF),
104-
origTargetTL.getLoweredType());
103+
SILValue resultScalar;
104+
if (Strategy == CastStrategy::Address) {
105+
resultScalar = SGF.B.createUnconditionalCheckedCastOpaque(
106+
Loc, operand.forward(SGF), origTargetTL.getLoweredType());
107+
} else {
108+
resultScalar = SGF.B.createUnconditionalCheckedCast(
109+
Loc, operand.forward(SGF), origTargetTL.getLoweredType());
110+
}
111+
105112
return RValue(SGF, Loc, TargetType,
106113
finishFromResultScalar(hasAbstraction, resultScalar,
107114
CastConsumptionKind::TakeAlways,

lib/SILOptimizer/Utils/SILInliner.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ InlineCost swift::instructionInlineCost(SILInstruction &I) {
392392
case ValueKind::UncheckedTakeEnumDataAddrInst:
393393
case ValueKind::UnconditionalCheckedCastInst:
394394
case ValueKind::UnconditionalCheckedCastAddrInst:
395+
case ValueKind::UnconditionalCheckedCastOpaqueInst:
395396
case ValueKind::UnmanagedToRefInst:
396397
case ValueKind::UnownedReleaseInst:
397398
case ValueKind::UnownedRetainInst:

lib/Serialization/DeserializeSIL.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1892,6 +1892,13 @@ bool SILDeserializer::readSILInstruction(SILFunction *Fn, SILBasicBlock *BB,
18921892
successBB, failureBB);
18931893
break;
18941894
}
1895+
case ValueKind::UnconditionalCheckedCastOpaqueInst: {
1896+
SILValue Val = getLocalValue(
1897+
ValID, getSILType(MF->getType(TyID2), (SILValueCategory)TyCategory2));
1898+
SILType Ty = getSILType(MF->getType(TyID), (SILValueCategory)TyCategory);
1899+
ResultVal = Builder.createUnconditionalCheckedCastOpaque(Loc, Val, Ty);
1900+
break;
1901+
}
18951902
case ValueKind::UnconditionalCheckedCastAddrInst:
18961903
case ValueKind::CheckedCastAddrBranchInst: {
18971904
CastConsumptionKind consumption = getCastConsumptionKind(ListOfValues[0]);

lib/Serialization/SerializeSIL.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,18 @@ void SILSerializer::writeSILInstruction(const SILInstruction &SI) {
13011301
llvm::makeArrayRef(listOfValues));
13021302
break;
13031303
}
1304+
case ValueKind::UnconditionalCheckedCastOpaqueInst: {
1305+
auto CI = cast<UnconditionalCheckedCastOpaqueInst>(&SI);
1306+
SILInstCastLayout::emitRecord(
1307+
Out, ScratchRecord, SILAbbrCodes[SILInstCastLayout::Code],
1308+
(unsigned)SI.getKind(), /*attr*/ 0,
1309+
S.addTypeRef(CI->getType().getSwiftRValueType()),
1310+
(unsigned)CI->getType().getCategory(),
1311+
S.addTypeRef(CI->getOperand()->getType().getSwiftRValueType()),
1312+
(unsigned)CI->getOperand()->getType().getCategory(),
1313+
addValueRef(CI->getOperand()));
1314+
break;
1315+
}
13041316
case ValueKind::UncheckedRefCastAddrInst: {
13051317
auto CI = cast<UncheckedRefCastAddrInst>(&SI);
13061318
ValueID listOfValues[] = {

test/SILGen/opaque_values_silgen.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,23 @@ func s150___________anyArg(_: Any) {}
244244
func s160_______callAnyArg() {
245245
s150___________anyArg(42)
246246
}
247+
248+
// Tests unconditional_checked_cast for opaque values
249+
// ---
250+
// CHECK-LABEL: sil hidden @_T020opaque_values_silgen21s170____force_convertxylF : $@convention(thin) <T> () -> @out T {
251+
// CHECK: bb0:
252+
// CHECK-NOT: alloc_stack
253+
// CHECK: [[INT_TYPE:%.*]] = metatype $@thin Int.Type
254+
// CHECK: [[INT_LIT:%.*]] = integer_literal $Builtin.Int2048, 42
255+
// CHECK: [[INT_ARG:%.*]] = apply %{{.*}}([[INT_LIT]], [[INT_TYPE]]) : $@convention(method) (Builtin.Int2048, @thin Int.Type) -> Int
256+
// CHECK: [[INT_CAST:%.*]] = unconditional_checked_cast_opaque [[INT_ARG]] : $Int to $T
257+
// CHECK: [[CAST_BORROW:%.*]] = begin_borrow [[INT_CAST]] : $T
258+
// CHECK: [[RETURN_VAL:%.*]] = copy_value [[CAST_BORROW]] : $T
259+
// CHECK: end_borrow [[CAST_BORROW]] from [[INT_CAST]] : $T, $T
260+
// CHECK: destroy_value [[INT_CAST]] : $T
261+
// CHECK: return [[RETURN_VAL]] : $T
262+
// CHECK-LABEL: } // end sil function '_T020opaque_values_silgen21s170____force_convertxylF'
263+
func s170____force_convert<T>() -> T {
264+
let x : T = 42 as! T
265+
return x
266+
}

utils/sil-mode.el

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,8 @@
153153
'words) . font-lock-keyword-face)
154154

155155
;; Checked Conversions
156-
`(,(regexp-opt '("unconditional_checked_cast" "unconditional_checked_cast_addr")
156+
`(,(regexp-opt '("unconditional_checked_cast" "unconditional_checked_cast_addr"
157+
"unconditional_checked_cast_opaque")
157158
'words) . font-lock-keyword-face)
158159
;; Runtime Failures
159160
`(,(regexp-opt '("cond_fail")

utils/vim/syntax/sil.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ syn keyword swiftKeyword init_existential_addr init_existential_opaque init_exis
4040
syn keyword swiftKeyword upcast address_to_pointer pointer_to_address pointer_to_thin_function unchecked_addr_cast unchecked_ref_cast unchecked_ref_cast_addr ref_to_raw_pointer ref_to_bridge_object ref_to_unmanaged unmanaged_to_ref raw_pointer_to_ref skipwhite
4141
syn keyword swiftKeyword convert_function thick_to_objc_metatype thin_function_to_pointer objc_to_thick_metatype thin_to_thick_function is_nonnull unchecked_ref_bit_cast unchecked_trivial_bit_cast bridge_object_to_ref bridge_object_to_word unchecked_bitwise_cast skipwhite
4242
syn keyword swiftKeyword objc_existential_metatype_to_object objc_metatype_to_object objc_protocol skipwhite
43-
syn keyword swiftKeyword unconditional_checked_cast unconditional_checked_cast_addr skipwhite
43+
syn keyword swiftKeyword unconditional_checked_cast unconditional_checked_cast_addr unconditional_checked_cast_opaque skipwhite
4444
syn keyword swiftKeyword cond_fail skipwhite
4545
syn keyword swiftKeyword unreachable return throw br cond_br switch_value select_enum select_enum_addr select_value switch_enum switch_enum_addr dynamic_method_br checked_cast_br checked_cast_addr_br skipwhite
4646
syn keyword swiftKeyword project_box project_existential_box project_value_buffer project_block_storage init_block_storage_header copy_block mark_dependence skipwhite

0 commit comments

Comments
 (0)