Skip to content

Commit 20c5dff

Browse files
committed
[builtin] Implement polymorphic builtins for all BUILTIN_BINARY_OPERATIONs.
TLDR: This patch introduces a new kind of builtin, "a polymorphic builtin". One calls it like any other builtin, e.x.: ``` Builtin.generic_add(x, y) ``` but it has a contract: it must be specialized to a concrete builtin by the time we hit Lowered SIL. In this commit, I add support for the following generic operations: Type | Op ------------------------ FloatOrVector |FAdd FloatOrVector |FDiv FloatOrVector |FMul FloatOrVector |FRem FloatOrVector |FSub IntegerOrVector|AShr IntegerOrVector|Add IntegerOrVector|And IntegerOrVector|ExactSDiv IntegerOrVector|ExactUDiv IntegerOrVector|LShr IntegerOrVector|Mul IntegerOrVector|Or IntegerOrVector|SDiv IntegerOrVector|SRem IntegerOrVector|Shl IntegerOrVector|Sub IntegerOrVector|UDiv IntegerOrVector|Xor Integer |URem NOTE: I only implemented support for the builtins in SIL and in SILGen. I am going to implement the optimizer parts of this in a separate series of commits. DISCUSSION ---------- Today there are polymorphic like instructions in LLVM-IR. Yet, at the swift and SIL level we represent these operations instead as Builtins whose names are resolved by splatting the builtin into the name. For example, adding two things in LLVM: ``` %2 = add i64 %0, %1 %2 = add <2 x i64> %0, %1 %2 = add <4 x i64> %0, %1 %2 = add <8 x i64> %0, %1 ``` Each of the add operations are done by the same polymorphic instruction. In constrast, we splat out these Builtins in swift today, i.e.: ``` let x, y: Builtin.Int32 Builtin.add_Int32(x, y) let x, y: Builtin.Vec4xInt32 Builtin.add_Vec4xInt32(x, y) ... ``` In SIL, we translate these verbatim and then IRGen just lowers them to the appropriate polymorphic instruction. Beyond being verbose, these prevent these Builtins (which need static types) from being used in polymorphic contexts where we can guarantee that eventually a static type will be provided. In contrast, the polymorphic builtins introduced in this commit can be passed any type, with the proviso that the expert user using this feature can guarantee that before we reach Lowered SIL, the generic_add has been eliminated. This is enforced by IRGen asserting if passed such a builtin and by the SILVerifier checking that the underlying builtin is never called once the module is in Lowered SIL. In forthcoming commits, I am going to add two optimizations that give the stdlib tool writer the tools needed to use this builtin: 1. I am going to add an optimization to constant propagation that changes a "generic_*" op to the type of its argument if the argument is a type that is valid for the builtin (i.e. integer or vector). 2. I am going to teach the SILCloner how to specialize these as it inlines. This ensures that when we transparent inline, we specialize the builtin automatically and can then form SSA at -Onone using predictable memory access operations. The main implication around these polymorphic builtins are that if an author is not able to specialize the builtin, they need to ensure that after constant propagation, the generic builtin has been DCEed. The general rules are that the -Onone optimizer will constant fold branches with constant integer operands. So if one can use a bool of some sort to trigger the operation, one can be guaranteed that the code will not codegen. I am considering putting in some sort of diagnostic to ensure that the stdlib writer has a good experience (e.x. get an error instead of crashing the compiler).
1 parent 059b0c8 commit 20c5dff

13 files changed

+820
-63
lines changed

include/swift/AST/Builtins.def

+90-24
Original file line numberDiff line numberDiff line change
@@ -51,32 +51,98 @@ BUILTIN_CAST_OR_BITCAST_OPERATION(SExtOrBitCast, "sextOrBitCast", "n")
5151
#undef BUILTIN_CAST_OR_BITCAST_OPERATION
5252

5353
/// Binary operations have type (T,T) -> T.
54+
///
55+
/// We define two different sorts of operations varying when T is static,
56+
/// specifically:
57+
///
58+
/// 1. Overloaded statically typed operations. E.x:
59+
///
60+
/// builtin "add_Vec4xInt32"(Vec4xInt32, Vec4xInt32) : Vec4xInt32.
61+
///
62+
/// 2. Polymorphic typed operations that are valid only in raw SIL. By the time
63+
/// diagnostic constant propagation runs, these must have as its operand a
64+
/// fully specialized type. If the builtin has a type that is not one of its
65+
/// overloaded types, diagnostic constant propagation will emit a diagnostic
66+
/// saying the builtin's type has not been fully resolved. Otherwise,
67+
/// diagnostic constant propagation will transform the builtin to the
68+
/// relevant static overloaded builtin form. E.x.:
69+
///
70+
/// builtin "add"(Self, Self) : Self // *error*
71+
///
72+
/// OR
73+
///
74+
/// builtin "generic_add"(Vec4xInt32, Vec4xInt32) : Vec4xInt32
75+
/// ->
76+
/// builtin "add_Vec4xInt32"(Vec4xInt32, Vec4xInt32) : Vec4xInt32
77+
///
78+
/// NOTE: If a polymorphic typed operation is not static by the time guaranteed
79+
/// constant propagation runs, we emit a diagnostic to inform the user (who is
80+
/// assumed to be an expert user) to tell them the value was unspecialized. The
81+
/// typical way this specialization occurs today is via transparent inlining
82+
/// since the transparent inliner devirtualizes and specializes as it goes. Of
83+
/// course this means mandatory inlining must /always/ occur before diagnostic
84+
/// constant propagation.
85+
///
86+
/// NOTE: Often times the builtin infrastructure wants to treat all
87+
/// binary operation builtins generic or not the same way. To ensure
88+
/// we support all use cases in the compiler, we do not declare the
89+
/// operations as part of this builtin since often times this macro is
90+
/// used to generic code. Instead, we stamp this out using the
91+
/// overloaded_static, polymorphic, and all suffixed operations.
5492
#ifndef BUILTIN_BINARY_OPERATION
55-
#define BUILTIN_BINARY_OPERATION(Id, Name, Attrs, Overload) \
56-
BUILTIN(Id, Name, Attrs)
93+
#define BUILTIN_BINARY_OPERATION(Id, Name, Attrs) BUILTIN(Id, Name, Attrs)
5794
#endif
58-
BUILTIN_BINARY_OPERATION(Add, "add", "n", IntegerOrVector)
59-
BUILTIN_BINARY_OPERATION(FAdd, "fadd", "n", FloatOrVector)
60-
BUILTIN_BINARY_OPERATION(And, "and", "n", IntegerOrVector)
61-
BUILTIN_BINARY_OPERATION(AShr, "ashr", "n", IntegerOrVector)
62-
BUILTIN_BINARY_OPERATION(LShr, "lshr", "n", IntegerOrVector)
63-
BUILTIN_BINARY_OPERATION(Or, "or", "n", IntegerOrVector)
64-
BUILTIN_BINARY_OPERATION(FDiv, "fdiv", "n", FloatOrVector)
65-
BUILTIN_BINARY_OPERATION(Mul, "mul", "n", IntegerOrVector)
66-
BUILTIN_BINARY_OPERATION(FMul, "fmul", "n", FloatOrVector)
67-
BUILTIN_BINARY_OPERATION(SDiv, "sdiv", "n", IntegerOrVector)
68-
BUILTIN_BINARY_OPERATION(ExactSDiv, "sdiv_exact", "n", IntegerOrVector)
69-
BUILTIN_BINARY_OPERATION(Shl, "shl", "n", IntegerOrVector)
70-
BUILTIN_BINARY_OPERATION(SRem, "srem", "n", IntegerOrVector)
71-
BUILTIN_BINARY_OPERATION(Sub, "sub", "n", IntegerOrVector)
72-
BUILTIN_BINARY_OPERATION(FSub, "fsub", "n", FloatOrVector)
73-
BUILTIN_BINARY_OPERATION(UDiv, "udiv", "n", IntegerOrVector)
74-
BUILTIN_BINARY_OPERATION(ExactUDiv, "udiv_exact", "n", IntegerOrVector)
75-
BUILTIN_BINARY_OPERATION(URem, "urem", "n", Integer)
76-
BUILTIN_BINARY_OPERATION(FRem, "frem", "n", FloatOrVector)
77-
BUILTIN_BINARY_OPERATION(Xor, "xor", "n", IntegerOrVector)
78-
// This builtin is an optimizer hint and always returns the first argument.
79-
BUILTIN_BINARY_OPERATION(Expect, "int_expect", "n", Integer)
95+
96+
#ifdef BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR
97+
#error "Do not define BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR before including this .def file"
98+
#endif
99+
100+
#define BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR(NAME) #NAME
101+
102+
#ifndef BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC
103+
#define BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(Id, Name, Attrs, Overload) \
104+
BUILTIN_BINARY_OPERATION(Id, Name, Attrs)
105+
#endif
106+
107+
#ifndef BUILTIN_BINARY_OPERATION_POLYMORPHIC
108+
#define BUILTIN_BINARY_OPERATION_POLYMORPHIC(Id, Name, Attrs) \
109+
BUILTIN_BINARY_OPERATION(Id, Name, Attrs)
110+
#endif
111+
112+
// TODO: This needs a better name. We stringify generic_ in *_{OVERLOADED_STATIC,POLYMORPHIC}
113+
#ifndef BUILTIN_BINARY_OPERATION_ALL
114+
#define BUILTIN_BINARY_OPERATION_ALL(Id, Name, Attrs, Overload) \
115+
BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(Id, BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR(Name), Attrs, Overload) \
116+
BUILTIN_BINARY_OPERATION_POLYMORPHIC(Generic##Id, BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR(generic_##Name), Attrs)
117+
#endif
118+
119+
// NOTE: Here we need our name field to be bare. We stringify them as
120+
// appropriately in BUILTIN_BINARY_OPERATION_{OVERLOADED_STATIC,POLYMORPHIC}.
121+
BUILTIN_BINARY_OPERATION_ALL(Add, add, "n", IntegerOrVector)
122+
BUILTIN_BINARY_OPERATION_ALL(FAdd, fadd, "n", FloatOrVector)
123+
BUILTIN_BINARY_OPERATION_ALL(And, and, "n", IntegerOrVector)
124+
BUILTIN_BINARY_OPERATION_ALL(AShr, ashr, "n", IntegerOrVector)
125+
BUILTIN_BINARY_OPERATION_ALL(LShr, lshr, "n", IntegerOrVector)
126+
BUILTIN_BINARY_OPERATION_ALL(Or, or, "n", IntegerOrVector)
127+
BUILTIN_BINARY_OPERATION_ALL(FDiv, fdiv, "n", FloatOrVector)
128+
BUILTIN_BINARY_OPERATION_ALL(Mul, mul, "n", IntegerOrVector)
129+
BUILTIN_BINARY_OPERATION_ALL(FMul, fmul, "n", FloatOrVector)
130+
BUILTIN_BINARY_OPERATION_ALL(SDiv, sdiv, "n", IntegerOrVector)
131+
BUILTIN_BINARY_OPERATION_ALL(ExactSDiv, sdiv_exact, "n", IntegerOrVector)
132+
BUILTIN_BINARY_OPERATION_ALL(Shl, shl, "n", IntegerOrVector)
133+
BUILTIN_BINARY_OPERATION_ALL(SRem, srem, "n", IntegerOrVector)
134+
BUILTIN_BINARY_OPERATION_ALL(Sub, sub, "n", IntegerOrVector)
135+
BUILTIN_BINARY_OPERATION_ALL(FSub, fsub, "n", FloatOrVector)
136+
BUILTIN_BINARY_OPERATION_ALL(UDiv, udiv, "n", IntegerOrVector)
137+
BUILTIN_BINARY_OPERATION_ALL(ExactUDiv, udiv_exact, "n", IntegerOrVector)
138+
BUILTIN_BINARY_OPERATION_ALL(URem, urem, "n", Integer)
139+
BUILTIN_BINARY_OPERATION_ALL(FRem, frem, "n", FloatOrVector)
140+
BUILTIN_BINARY_OPERATION_ALL(Xor, xor, "n", IntegerOrVector)
141+
BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(Expect, "int_expect", "n", Integer)
142+
#undef BUILTIN_BINARY_OPERATION_ALL
143+
#undef BUILTIN_BINARY_OPERATION_POLYMORPHIC
144+
#undef BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC
145+
#undef BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR
80146
#undef BUILTIN_BINARY_OPERATION
81147

82148
/// These builtins are analogous the similarly named llvm intrinsics. The

include/swift/AST/Builtins.h

+5
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ enum class BuiltinValueKind {
8383
#include "swift/AST/Builtins.def"
8484
};
8585

86+
/// Returns true if this is a polymorphic builtin that is only valid
87+
/// in raw sil and thus must be resolved to have concrete types by the
88+
/// time we are in canonical SIL.
89+
bool isPolymorphicBuiltin(BuiltinValueKind Id);
90+
8691
/// Decode the type list of a builtin (e.g. mul_Int32) and return the base
8792
/// name (e.g. "mul").
8893
StringRef getBuiltinBaseName(ASTContext &C, StringRef Name,

include/swift/SIL/PatternMatch.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ using BuiltinApplyTy = typename Apply_match<BuiltinValueKind, Tys...>::Ty;
649649
#define BUILTIN_CAST_OR_BITCAST_OPERATION(Id, Name, Attrs) \
650650
BUILTIN_UNARY_OP_MATCH_WITH_ARG_MATCHER(Id, Id)
651651

652-
#define BUILTIN_BINARY_OPERATION(Id, Name, Attrs, Overload) \
652+
#define BUILTIN_BINARY_OPERATION_ALL(Id, Name, Attrs, Overload) \
653653
BUILTIN_BINARY_OP_MATCH_WITH_ARG_MATCHER(Id, Id)
654654

655655
#define BUILTIN_BINARY_PREDICATE(Id, Name, Attrs, Overload) \

lib/AST/Builtins.cpp

+40-3
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,15 @@ static ValueDecl *getOnceOperation(ASTContext &Context,
11811181
}
11821182
}
11831183

1184+
static ValueDecl *getPolymorphicBinaryOperation(ASTContext &ctx,
1185+
Identifier id) {
1186+
BuiltinGenericSignatureBuilder builder(ctx);
1187+
builder.addParameter(makeGenericParam());
1188+
builder.addParameter(makeGenericParam());
1189+
builder.setResult(makeGenericParam());
1190+
return builder.build(id);
1191+
}
1192+
11841193
/// An array of the overloaded builtin kinds.
11851194
static const OverloadedBuiltinKind OverloadedBuiltinKinds[] = {
11861195
OverloadedBuiltinKind::None,
@@ -1191,8 +1200,10 @@ static const OverloadedBuiltinKind OverloadedBuiltinKinds[] = {
11911200
OverloadedBuiltinKind::Special,
11921201
#define BUILTIN_CAST_OR_BITCAST_OPERATION(id, attrs, name) \
11931202
OverloadedBuiltinKind::Special,
1194-
#define BUILTIN_BINARY_OPERATION(id, name, attrs, overload) \
1195-
OverloadedBuiltinKind::overload,
1203+
#define BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(id, name, attrs, overload) \
1204+
OverloadedBuiltinKind::overload,
1205+
#define BUILTIN_BINARY_OPERATION_POLYMORPHIC(id, name, attrs) \
1206+
OverloadedBuiltinKind::Special,
11961207
#define BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(id, name, _, attrs, overload) \
11971208
OverloadedBuiltinKind::overload,
11981209
#define BUILTIN_BINARY_PREDICATE(id, name, attrs, overload) \
@@ -1777,11 +1788,22 @@ ValueDecl *swift::getBuiltinValueDecl(ASTContext &Context, Identifier Id) {
17771788
return getEndUnpairedAccessOperation(Context, Id);
17781789

17791790
#define BUILTIN(id, name, Attrs)
1780-
#define BUILTIN_BINARY_OPERATION(id, name, attrs, overload) case BuiltinValueKind::id:
1791+
#define BUILTIN_BINARY_OPERATION(id, name, attrs)
1792+
#define BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(id, name, attrs, overload) \
1793+
case BuiltinValueKind::id:
17811794
#include "swift/AST/Builtins.def"
17821795
if (Types.size() != 1) return nullptr;
17831796
return getBinaryOperation(Id, Types[0]);
17841797

1798+
#define BUILTIN(id, name, attrs)
1799+
#define BUILTIN_BINARY_OPERATION(id, name, attrs)
1800+
#define BUILTIN_BINARY_OPERATION_POLYMORPHIC(id, name, attrs) \
1801+
case BuiltinValueKind::id:
1802+
#include "swift/AST/Builtins.def"
1803+
if (!Types.empty())
1804+
return nullptr;
1805+
return getPolymorphicBinaryOperation(Context, Id);
1806+
17851807
#define BUILTIN(id, name, Attrs)
17861808
#define BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(id, name, _, attrs, overload) case BuiltinValueKind::id:
17871809
#include "swift/AST/Builtins.def"
@@ -2034,6 +2056,21 @@ StringRef swift::getBuiltinName(BuiltinValueKind ID) {
20342056
llvm_unreachable("bad BuiltinValueKind");
20352057
}
20362058

2059+
bool swift::isPolymorphicBuiltin(BuiltinValueKind id) {
2060+
switch (id) {
2061+
case BuiltinValueKind::None:
2062+
llvm_unreachable("no builtin kind");
2063+
#define BUILTIN(Id, Name, Attrs) \
2064+
case BuiltinValueKind::Id: \
2065+
return false;
2066+
#define BUILTIN_BINARY_OPERATION_POLYMORPHIC(Id, Name, Attrs) \
2067+
case BuiltinValueKind::Id: \
2068+
return true;
2069+
#include "swift/AST/Builtins.def"
2070+
}
2071+
llvm_unreachable("bad BuiltinValueKind");
2072+
}
2073+
20372074
BuiltinTypeKind BuiltinType::getBuiltinTypeKind() const {
20382075
// If we do not have a vector or an integer our job is easy.
20392076
return BuiltinTypeKind(std::underlying_type<TypeKind>::type(getKind()));

lib/IRGen/GenBuiltin.cpp

+11-7
Original file line numberDiff line numberDiff line change
@@ -305,14 +305,18 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
305305
if (Builtin.ID == BuiltinValueKind::id) \
306306
return emitCastOrBitCastBuiltin(IGF, resultType, out, args, \
307307
BuiltinValueKind::id);
308-
309-
#define BUILTIN_BINARY_OPERATION(id, name, attrs, overload) \
310-
if (Builtin.ID == BuiltinValueKind::id) { \
311-
llvm::Value *lhs = args.claimNext(); \
312-
llvm::Value *rhs = args.claimNext(); \
313-
llvm::Value *v = IGF.Builder.Create##id(lhs, rhs); \
314-
return out.add(v); \
308+
309+
#define BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(id, name, attrs, overload) \
310+
if (Builtin.ID == BuiltinValueKind::id) { \
311+
llvm::Value *lhs = args.claimNext(); \
312+
llvm::Value *rhs = args.claimNext(); \
313+
llvm::Value *v = IGF.Builder.Create##id(lhs, rhs); \
314+
return out.add(v); \
315315
}
316+
#define BUILTIN_BINARY_OPERATION_POLYMORPHIC(id, name, attrs) \
317+
assert(Builtin.ID != BuiltinValueKind::id && \
318+
"This builtin should never be seen by IRGen. It is invalid in " \
319+
"Lowered sil");
316320

317321
#define BUILTIN_RUNTIME_CALL(id, name, attrs) \
318322
if (Builtin.ID == BuiltinValueKind::id) { \

lib/SIL/OperandOwnership.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -917,10 +917,13 @@ ANY_OWNERSHIP_BUILTIN(ErrorInMain)
917917
ANY_OWNERSHIP_BUILTIN(UnexpectedError)
918918
ANY_OWNERSHIP_BUILTIN(WillThrow)
919919
ANY_OWNERSHIP_BUILTIN(AShr)
920+
ANY_OWNERSHIP_BUILTIN(GenericAShr)
920921
ANY_OWNERSHIP_BUILTIN(Add)
922+
ANY_OWNERSHIP_BUILTIN(GenericAdd)
921923
ANY_OWNERSHIP_BUILTIN(Alignof)
922924
ANY_OWNERSHIP_BUILTIN(AllocRaw)
923925
ANY_OWNERSHIP_BUILTIN(And)
926+
ANY_OWNERSHIP_BUILTIN(GenericAnd)
924927
ANY_OWNERSHIP_BUILTIN(AssertConf)
925928
ANY_OWNERSHIP_BUILTIN(AssignCopyArrayNoAlias)
926929
ANY_OWNERSHIP_BUILTIN(AssignCopyArrayFrontToBack)
@@ -940,9 +943,12 @@ ANY_OWNERSHIP_BUILTIN(CopyArray)
940943
ANY_OWNERSHIP_BUILTIN(DeallocRaw)
941944
ANY_OWNERSHIP_BUILTIN(DestroyArray)
942945
ANY_OWNERSHIP_BUILTIN(ExactSDiv)
946+
ANY_OWNERSHIP_BUILTIN(GenericExactSDiv)
943947
ANY_OWNERSHIP_BUILTIN(ExactUDiv)
948+
ANY_OWNERSHIP_BUILTIN(GenericExactUDiv)
944949
ANY_OWNERSHIP_BUILTIN(ExtractElement)
945950
ANY_OWNERSHIP_BUILTIN(FAdd)
951+
ANY_OWNERSHIP_BUILTIN(GenericFAdd)
946952
ANY_OWNERSHIP_BUILTIN(FCMP_OEQ)
947953
ANY_OWNERSHIP_BUILTIN(FCMP_OGE)
948954
ANY_OWNERSHIP_BUILTIN(FCMP_OGT)
@@ -958,14 +964,18 @@ ANY_OWNERSHIP_BUILTIN(FCMP_ULT)
958964
ANY_OWNERSHIP_BUILTIN(FCMP_UNE)
959965
ANY_OWNERSHIP_BUILTIN(FCMP_UNO)
960966
ANY_OWNERSHIP_BUILTIN(FDiv)
967+
ANY_OWNERSHIP_BUILTIN(GenericFDiv)
961968
ANY_OWNERSHIP_BUILTIN(FMul)
969+
ANY_OWNERSHIP_BUILTIN(GenericFMul)
962970
ANY_OWNERSHIP_BUILTIN(FNeg)
963971
ANY_OWNERSHIP_BUILTIN(FPExt)
964972
ANY_OWNERSHIP_BUILTIN(FPToSI)
965973
ANY_OWNERSHIP_BUILTIN(FPToUI)
966974
ANY_OWNERSHIP_BUILTIN(FPTrunc)
967975
ANY_OWNERSHIP_BUILTIN(FRem)
976+
ANY_OWNERSHIP_BUILTIN(GenericFRem)
968977
ANY_OWNERSHIP_BUILTIN(FSub)
978+
ANY_OWNERSHIP_BUILTIN(GenericFSub)
969979
ANY_OWNERSHIP_BUILTIN(Fence)
970980
ANY_OWNERSHIP_BUILTIN(GetObjCTypeEncoding)
971981
ANY_OWNERSHIP_BUILTIN(ICMP_EQ)
@@ -987,29 +997,36 @@ ANY_OWNERSHIP_BUILTIN(IsConcrete)
987997
ANY_OWNERSHIP_BUILTIN(IsBitwiseTakable)
988998
ANY_OWNERSHIP_BUILTIN(IsSameMetatype)
989999
ANY_OWNERSHIP_BUILTIN(LShr)
1000+
ANY_OWNERSHIP_BUILTIN(GenericLShr)
9901001
ANY_OWNERSHIP_BUILTIN(Mul)
1002+
ANY_OWNERSHIP_BUILTIN(GenericMul)
9911003
ANY_OWNERSHIP_BUILTIN(OnFastPath)
9921004
ANY_OWNERSHIP_BUILTIN(Once)
9931005
ANY_OWNERSHIP_BUILTIN(OnceWithContext)
9941006
ANY_OWNERSHIP_BUILTIN(Or)
1007+
ANY_OWNERSHIP_BUILTIN(GenericOr)
9951008
ANY_OWNERSHIP_BUILTIN(PtrToInt)
9961009
ANY_OWNERSHIP_BUILTIN(SAddOver)
9971010
ANY_OWNERSHIP_BUILTIN(SDiv)
1011+
ANY_OWNERSHIP_BUILTIN(GenericSDiv)
9981012
ANY_OWNERSHIP_BUILTIN(SExt)
9991013
ANY_OWNERSHIP_BUILTIN(SExtOrBitCast)
10001014
ANY_OWNERSHIP_BUILTIN(SIToFP)
10011015
ANY_OWNERSHIP_BUILTIN(SMulOver)
10021016
ANY_OWNERSHIP_BUILTIN(SRem)
1017+
ANY_OWNERSHIP_BUILTIN(GenericSRem)
10031018
ANY_OWNERSHIP_BUILTIN(SSubOver)
10041019
ANY_OWNERSHIP_BUILTIN(SToSCheckedTrunc)
10051020
ANY_OWNERSHIP_BUILTIN(SToUCheckedTrunc)
10061021
ANY_OWNERSHIP_BUILTIN(Expect)
10071022
ANY_OWNERSHIP_BUILTIN(Shl)
1023+
ANY_OWNERSHIP_BUILTIN(GenericShl)
10081024
ANY_OWNERSHIP_BUILTIN(Sizeof)
10091025
ANY_OWNERSHIP_BUILTIN(StaticReport)
10101026
ANY_OWNERSHIP_BUILTIN(Strideof)
10111027
ANY_OWNERSHIP_BUILTIN(StringObjectOr)
10121028
ANY_OWNERSHIP_BUILTIN(Sub)
1029+
ANY_OWNERSHIP_BUILTIN(GenericSub)
10131030
ANY_OWNERSHIP_BUILTIN(TakeArrayNoAlias)
10141031
ANY_OWNERSHIP_BUILTIN(TakeArrayBackToFront)
10151032
ANY_OWNERSHIP_BUILTIN(TakeArrayFrontToBack)
@@ -1018,15 +1035,18 @@ ANY_OWNERSHIP_BUILTIN(TruncOrBitCast)
10181035
ANY_OWNERSHIP_BUILTIN(TSanInoutAccess)
10191036
ANY_OWNERSHIP_BUILTIN(UAddOver)
10201037
ANY_OWNERSHIP_BUILTIN(UDiv)
1038+
ANY_OWNERSHIP_BUILTIN(GenericUDiv)
10211039
ANY_OWNERSHIP_BUILTIN(UIToFP)
10221040
ANY_OWNERSHIP_BUILTIN(UMulOver)
10231041
ANY_OWNERSHIP_BUILTIN(URem)
1042+
ANY_OWNERSHIP_BUILTIN(GenericURem)
10241043
ANY_OWNERSHIP_BUILTIN(USubOver)
10251044
ANY_OWNERSHIP_BUILTIN(UToSCheckedTrunc)
10261045
ANY_OWNERSHIP_BUILTIN(UToUCheckedTrunc)
10271046
ANY_OWNERSHIP_BUILTIN(Unreachable)
10281047
ANY_OWNERSHIP_BUILTIN(UnsafeGuaranteedEnd)
10291048
ANY_OWNERSHIP_BUILTIN(Xor)
1049+
ANY_OWNERSHIP_BUILTIN(GenericXor)
10301050
ANY_OWNERSHIP_BUILTIN(ZExt)
10311051
ANY_OWNERSHIP_BUILTIN(ZExtOrBitCast)
10321052
ANY_OWNERSHIP_BUILTIN(ZeroInitializer)

lib/SIL/SILVerifier.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,10 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
16401640
// actual ValueDecl. Otherwise, we have an invalid builtin.
16411641
require(getBuiltinValueDecl(BI->getModule().getASTContext(), BI->getName()),
16421642
"Invalid builtin name?!");
1643+
1644+
require(BI->getModule().getStage() != SILStage::Lowered ||
1645+
!isPolymorphicBuiltin(*BI->getBuiltinKind()),
1646+
"Polymorphic builtins are illegal in lowered SIL?!");
16431647
}
16441648

16451649
void checkFunctionRefBaseInst(FunctionRefBaseInst *FRI) {

0 commit comments

Comments
 (0)