mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Ideally we'd be able to use the llvm interleave2 and deinterleave2 intrinsics instead of adding these, but deinterleave currently isn't available from Swift, and even if you hack that in, the codegen from LLVM is worse than what shufflevector produces for both x86 and arm. So in the medium-term we'll use these builtins, and hope to remove them in favor of [de]interleave2 at some future point.
1207 lines
54 KiB
C++
1207 lines
54 KiB
C++
//===--- Builtins.def - Builtins Macro Metaprogramming Database -*- C++ -*-===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the database of builtin functions.
|
|
//
|
|
// BUILTIN(Id, Name, Attrs)
|
|
// - Id is an identifier suitable for use in C++
|
|
// - Name is a string literal for the name to which the builtin should be
|
|
// bound in Swift
|
|
// - Attrs specifies information about attributes of the function:
|
|
// n -> readnone
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// Cast operations have type T1 -> T2.
|
|
#ifndef BUILTIN_CAST_OPERATION
|
|
#define BUILTIN_CAST_OPERATION(Id, Name, Attrs) BUILTIN(Id, Name, Attrs)
|
|
#endif
|
|
BUILTIN_CAST_OPERATION(Trunc , "trunc", "n")
|
|
BUILTIN_CAST_OPERATION(ZExt , "zext", "n")
|
|
BUILTIN_CAST_OPERATION(SExt , "sext", "n")
|
|
BUILTIN_CAST_OPERATION(FPToUI , "fptoui", "n")
|
|
BUILTIN_CAST_OPERATION(FPToSI , "fptosi", "n")
|
|
BUILTIN_CAST_OPERATION(UIToFP , "uitofp", "n")
|
|
BUILTIN_CAST_OPERATION(SIToFP , "sitofp", "n")
|
|
BUILTIN_CAST_OPERATION(FPTrunc , "fptrunc", "n")
|
|
BUILTIN_CAST_OPERATION(FPExt , "fpext", "n")
|
|
BUILTIN_CAST_OPERATION(PtrToInt, "ptrtoint", "n")
|
|
BUILTIN_CAST_OPERATION(IntToPtr, "inttoptr", "n")
|
|
BUILTIN_CAST_OPERATION(BitCast , "bitcast", "n")
|
|
|
|
/// Cast-or-bitcast operations have type T1 -> T2.
|
|
/// T1 and T2 may be the same size, unlike the corresponding true casts.
|
|
#ifndef BUILTIN_CAST_OR_BITCAST_OPERATION
|
|
#define BUILTIN_CAST_OR_BITCAST_OPERATION(Id, Name, Attrs) BUILTIN(Id, Name, Attrs)
|
|
#endif
|
|
BUILTIN_CAST_OR_BITCAST_OPERATION(TruncOrBitCast, "truncOrBitCast", "n")
|
|
BUILTIN_CAST_OR_BITCAST_OPERATION(ZExtOrBitCast, "zextOrBitCast", "n")
|
|
BUILTIN_CAST_OR_BITCAST_OPERATION(SExtOrBitCast, "sextOrBitCast", "n")
|
|
|
|
/// Binary operations have type (T,T) -> T.
|
|
///
|
|
/// We define two different sorts of operations varying when T is static,
|
|
/// specifically:
|
|
///
|
|
/// 1. Overloaded statically typed operations. E.x:
|
|
///
|
|
/// builtin "add_Vec4xInt32"(Vec4xInt32, Vec4xInt32) : Vec4xInt32.
|
|
///
|
|
/// 2. Polymorphic typed operations that are valid only in raw SIL. By the time
|
|
/// diagnostic constant propagation runs, these must have as its operand a
|
|
/// fully specialized type. If the builtin has a type that is not one of its
|
|
/// overloaded types, diagnostic constant propagation will emit a diagnostic
|
|
/// saying the builtin's type has not been fully resolved. Otherwise,
|
|
/// diagnostic constant propagation will transform the builtin to the
|
|
/// relevant static overloaded builtin form. E.x.:
|
|
///
|
|
/// builtin "add"(Self, Self) : Self // *error*
|
|
///
|
|
/// OR
|
|
///
|
|
/// builtin "generic_add"(Vec4xInt32, Vec4xInt32) : Vec4xInt32
|
|
/// ->
|
|
/// builtin "add_Vec4xInt32"(Vec4xInt32, Vec4xInt32) : Vec4xInt32
|
|
///
|
|
/// NOTE: If a polymorphic typed operation is not static by the time guaranteed
|
|
/// constant propagation runs, we emit a diagnostic to inform the user (who is
|
|
/// assumed to be an expert user) to tell them the value was unspecialized. The
|
|
/// typical way this specialization occurs today is via transparent inlining
|
|
/// since the transparent inliner devirtualizes and specializes as it goes. Of
|
|
/// course this means mandatory inlining must /always/ occur before diagnostic
|
|
/// constant propagation.
|
|
///
|
|
/// NOTE: Often times the builtin infrastructure wants to treat all
|
|
/// binary operation builtins generic or not the same way. To ensure
|
|
/// we support all use cases in the compiler, we do not declare the
|
|
/// operations as part of this builtin since often times this macro is
|
|
/// used to generic code. Instead, we stamp this out using the
|
|
/// overloaded_static, polymorphic, and all suffixed operations.
|
|
#ifndef BUILTIN_BINARY_OPERATION
|
|
#define BUILTIN_BINARY_OPERATION(Id, Name, Attrs) BUILTIN(Id, Name, Attrs)
|
|
#endif
|
|
|
|
#ifdef BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR
|
|
#error "Do not define BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR before including this .def file"
|
|
#endif
|
|
|
|
#define BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR(NAME) #NAME
|
|
|
|
#ifndef BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC
|
|
#define BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(Id, Name, Attrs, Overload) \
|
|
BUILTIN_BINARY_OPERATION(Id, Name, Attrs)
|
|
#endif
|
|
|
|
#ifndef BUILTIN_BINARY_OPERATION_POLYMORPHIC
|
|
#define BUILTIN_BINARY_OPERATION_POLYMORPHIC(Id, Name) \
|
|
BUILTIN_BINARY_OPERATION(Id, Name, "")
|
|
#endif
|
|
|
|
// TODO: This needs a better name. We stringify generic_ in *_{OVERLOADED_STATIC,POLYMORPHIC}
|
|
#ifndef BUILTIN_BINARY_OPERATION_ALL
|
|
#define BUILTIN_BINARY_OPERATION_ALL(Id, Name, Attrs, Overload) \
|
|
BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(Id, BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR(Name), Attrs, Overload) \
|
|
BUILTIN_BINARY_OPERATION_POLYMORPHIC(Generic##Id, BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR(generic_##Name))
|
|
#endif
|
|
|
|
// NOTE: Here we need our name field to be bare. We stringify them as
|
|
// appropriately in BUILTIN_BINARY_OPERATION_{OVERLOADED_STATIC,POLYMORPHIC}.
|
|
BUILTIN_BINARY_OPERATION_ALL(Add, add, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(FAdd, fadd, "n", FloatOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(And, and, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(AShr, ashr, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(LShr, lshr, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(Or, or, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(FDiv, fdiv, "n", FloatOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(Mul, mul, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(FMul, fmul, "n", FloatOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(SDiv, sdiv, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(ExactSDiv, sdiv_exact, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(Shl, shl, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(SRem, srem, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(Sub, sub, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(FSub, fsub, "n", FloatOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(UDiv, udiv, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(ExactUDiv, udiv_exact, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(URem, urem, "n", Integer)
|
|
BUILTIN_BINARY_OPERATION_ALL(FRem, frem, "n", FloatOrVector)
|
|
BUILTIN_BINARY_OPERATION_ALL(Xor, xor, "n", IntegerOrVector)
|
|
BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC(Expect, "int_expect", "n", Integer)
|
|
|
|
/// These builtins are analogous the similarly named llvm intrinsics. The
|
|
/// difference between the two is that these are not expected to overflow,
|
|
/// so we should produce a compile time error if we can statically prove
|
|
/// that they do.
|
|
#ifndef BUILTIN_BINARY_OPERATION_WITH_OVERFLOW
|
|
#define BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(Id, Name, UncheckedID, Attrs, Overload) \
|
|
BUILTIN(Id, Name, Attrs)
|
|
#endif
|
|
BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(SAddOver,
|
|
"sadd_with_overflow", Add, "n", Integer)
|
|
BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(UAddOver,
|
|
"uadd_with_overflow", Add, "n", Integer)
|
|
BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(SSubOver,
|
|
"ssub_with_overflow", Sub, "n", Integer)
|
|
BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(USubOver,
|
|
"usub_with_overflow", Sub, "n", Integer)
|
|
BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(SMulOver,
|
|
"smul_with_overflow", Mul, "n", Integer)
|
|
BUILTIN_BINARY_OPERATION_WITH_OVERFLOW(UMulOver,
|
|
"umul_with_overflow", Mul, "n", Integer)
|
|
|
|
/// Unary operations have type (T) -> T.
|
|
#ifndef BUILTIN_UNARY_OPERATION
|
|
#define BUILTIN_UNARY_OPERATION(Id, Name, Attrs, Overload) \
|
|
BUILTIN(Id, Name, Attrs)
|
|
#endif
|
|
|
|
// "fneg" is a separate builtin because its LLVM representation is
|
|
// 'fsub -0.0, %x', but defining it in swift as
|
|
// 'func [prefix] -(x) { -0.0 - x }' would be infinitely recursive.
|
|
BUILTIN_UNARY_OPERATION(FNeg, "fneg", "n", FloatOrVector)
|
|
|
|
// Returns the argument and specifies that the value is not negative.
|
|
// It has only an effect if the argument is a load or call.
|
|
// TODO: consider printing a warning if it is not used on a load or call.
|
|
BUILTIN_UNARY_OPERATION(AssumeNonNegative, "assumeNonNegative", "n", Integer)
|
|
// It only works on i1.
|
|
BUILTIN_UNARY_OPERATION(AssumeTrue, "assume", "", Integer)
|
|
// Converts poison/undef to an indeterminate but valid value.
|
|
BUILTIN_UNARY_OPERATION(Freeze, "freeze", "n", IntegerOrVector)
|
|
|
|
// Binary predicates have type (T,T) -> i1 or (T, T) -> Vector<i1> for scalars
|
|
// and vectors, respectively.
|
|
#ifndef BUILTIN_BINARY_PREDICATE
|
|
#define BUILTIN_BINARY_PREDICATE(Id, Name, Attrs, Overload) \
|
|
BUILTIN(Id, Name, Attrs)
|
|
#endif
|
|
BUILTIN_BINARY_PREDICATE(ICMP_EQ, "cmp_eq", "n", IntegerOrRawPointerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(ICMP_NE, "cmp_ne", "n", IntegerOrRawPointerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(ICMP_SLE, "cmp_sle", "n", IntegerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(ICMP_SLT, "cmp_slt", "n", IntegerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(ICMP_SGE, "cmp_sge", "n", IntegerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(ICMP_SGT, "cmp_sgt", "n", IntegerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(ICMP_ULE, "cmp_ule", "n", IntegerOrRawPointerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(ICMP_ULT, "cmp_ult", "n", IntegerOrRawPointerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(ICMP_UGE, "cmp_uge", "n", IntegerOrRawPointerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(ICMP_UGT, "cmp_ugt", "n", IntegerOrRawPointerOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_OEQ, "fcmp_oeq", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_OGT, "fcmp_ogt", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_OGE, "fcmp_oge", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_OLT, "fcmp_olt", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_OLE, "fcmp_ole", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_ONE, "fcmp_one", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_ORD, "fcmp_ord", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_UEQ, "fcmp_ueq", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_UGT, "fcmp_ugt", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_UGE, "fcmp_uge", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_ULT, "fcmp_ult", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_ULE, "fcmp_ule", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_UNE, "fcmp_une", "n", FloatOrVector)
|
|
BUILTIN_BINARY_PREDICATE(FCMP_UNO, "fcmp_uno", "n", FloatOrVector)
|
|
|
|
// BUILTIN_SIL_OPERATION - Operations that can be lowered to SIL instructions.
|
|
// These have various types.
|
|
// Since these operations will be lowered to SIL Instructions, we do not
|
|
// assign any attributes on them.
|
|
#ifndef BUILTIN_SIL_OPERATION
|
|
#define BUILTIN_SIL_OPERATION(Id, Name, Overload) BUILTIN(Id, Name, "")
|
|
#endif
|
|
|
|
/// retain: T -> ()
|
|
BUILTIN_SIL_OPERATION(Retain, "retain", Special)
|
|
|
|
/// release: T -> ()
|
|
BUILTIN_SIL_OPERATION(Release, "release", Special)
|
|
|
|
/// autorelease: T -> ()
|
|
BUILTIN_SIL_OPERATION(Autorelease, "autorelease", Special)
|
|
|
|
/// Load has type (Builtin.RawPointer) -> T
|
|
BUILTIN_SIL_OPERATION(Load, "load", Special)
|
|
|
|
/// LoadRaw has type (Builtin.RawPointer) -> T
|
|
/// This is a load of T from raw memory.
|
|
/// Its address does not adhere to strict aliasing.
|
|
BUILTIN_SIL_OPERATION(LoadRaw, "loadRaw", Special)
|
|
|
|
/// LoadInvariant has type (Builtin.RawPointer) -> T
|
|
/// This is a load of T from raw memory.
|
|
/// The load is marked as invariant.
|
|
BUILTIN_SIL_OPERATION(LoadInvariant, "loadInvariant", Special)
|
|
|
|
/// Take has type (Builtin.RawPointer) -> T
|
|
BUILTIN_SIL_OPERATION(Take, "take", Special)
|
|
|
|
/// Destroy has type (T.Type, Builtin.RawPointer) -> ()
|
|
BUILTIN_SIL_OPERATION(Destroy, "destroy", Special)
|
|
|
|
/// Assign has type (T, Builtin.RawPointer) -> ()
|
|
BUILTIN_SIL_OPERATION(Assign, "assign", Special)
|
|
|
|
/// Init has type (T, Builtin.RawPointer) -> ()
|
|
BUILTIN_SIL_OPERATION(Init, "initialize", Special)
|
|
|
|
/// StoreRaw has type (T, Builtin.RawPointer) -> ()
|
|
/// Stores a T to raw memory.
|
|
/// Its address does not adhere to strict aliasing.
|
|
/// See also LoadRaw.
|
|
BUILTIN_SIL_OPERATION(StoreRaw, "storeRaw", Special)
|
|
|
|
/// CastToNativeObject has type (T) -> Builtin.NativeObject.
|
|
///
|
|
/// This builtin asserts if the underlying type /could/ be objc.
|
|
BUILTIN_SIL_OPERATION(CastToNativeObject, "castToNativeObject", Special)
|
|
|
|
/// UnsafeCastToNativeObject has type (T) -> Builtin.NativeObject.
|
|
///
|
|
/// This builtin does not check if the underlying type /could/ be objc.
|
|
BUILTIN_SIL_OPERATION(UnsafeCastToNativeObject, "unsafeCastToNativeObject", Special)
|
|
|
|
/// CastFromNativeObject has type (Builtin.NativeObject) -> T
|
|
BUILTIN_SIL_OPERATION(CastFromNativeObject, "castFromNativeObject", Special)
|
|
|
|
/// CastToBridgeObject has type (T, Builtin.Word) -> Builtin.BridgeObject.
|
|
/// It sets the BridgeObject to the bitwise OR of its operands.
|
|
/// It is assumed that
|
|
///
|
|
/// castReferenceFromBridgeObject(castToBridgeObject(ref, x)) === ref
|
|
///
|
|
/// regardless of what x is.
|
|
/// x thus must not have any bits set that would change the heap
|
|
/// object pointer value, nor may it have the native/ObjC discriminator bit set,
|
|
/// nor may it have any bits set if the first operand is an ObjC tagged pointer,
|
|
/// or else undefined behavior will ensue.
|
|
BUILTIN_SIL_OPERATION(CastToBridgeObject, "castToBridgeObject", Special)
|
|
|
|
/// ValueToBridgeObject has type (T) -> Builtin.BridgeObject.
|
|
/// It sets the BridgeObject to a tagged pointer representation holding its
|
|
// operands by tagging and shifting the operand if needed.
|
|
///
|
|
/// valueToBridgeObject(x) === (x << _swift_abi_ObjCReservedLowBits) |
|
|
/// _swift_BridgeObject_TaggedPointerBits
|
|
///
|
|
/// x thus must not be using any high bits shifted away (via _swift_abi_ObjCReservedLowBits)
|
|
/// or the tag bits post-shift.
|
|
/// ARC operations on such tagged values are NOPs.
|
|
BUILTIN_SIL_OPERATION(ValueToBridgeObject, "valueToBridgeObject", Special)
|
|
|
|
/// CastReferenceFromBridgeObject has type (Builtin.BridgeObject) -> T.
|
|
/// It recovers the heap object reference by masking spare bits from the
|
|
/// BridgeObject.
|
|
BUILTIN_SIL_OPERATION(CastReferenceFromBridgeObject,
|
|
"castReferenceFromBridgeObject",
|
|
Special)
|
|
|
|
/// CastBitPatternFromBridgeObject has type (Builtin.BridgeObject) -> Builtin.Word.
|
|
/// It presents the raw bit pattern of the BridgeObject as
|
|
BUILTIN_SIL_OPERATION(CastBitPatternFromBridgeObject,
|
|
"castBitPatternFromBridgeObject",
|
|
Special)
|
|
|
|
/// ClassifyBridgeObject has type:
|
|
/// (Builtin.BridgeObject) -> (Builtin.Int1, Builtin.Int1).
|
|
/// It interprets the bits mangled into a bridge object, returning whether it is
|
|
/// an Objective-C object or tagged pointer representation.
|
|
BUILTIN_SIL_OPERATION(ClassifyBridgeObject, "classifyBridgeObject", Special)
|
|
|
|
|
|
/// BridgeToRawPointer has type (T) -> Builtin.RawPointer
|
|
BUILTIN_SIL_OPERATION(BridgeToRawPointer, "bridgeToRawPointer", Special)
|
|
|
|
/// BridgeFromRawPointer (Builtin.RawPointer) -> T
|
|
/// SILGen requires that T is a single retainable pointer.
|
|
/// Bridging to/from a raw pointer does not imply a retain.
|
|
BUILTIN_SIL_OPERATION(BridgeFromRawPointer, "bridgeFromRawPointer", Special)
|
|
|
|
/// castReference has type T -> U.
|
|
/// T and U must be convertible to AnyObject.
|
|
BUILTIN_SIL_OPERATION(CastReference, "castReference", Special)
|
|
|
|
/// reinterpretCast has type T -> U.
|
|
BUILTIN_SIL_OPERATION(ReinterpretCast, "reinterpretCast", Special)
|
|
|
|
/// addressof (inout T) -> Builtin.RawPointer
|
|
/// Returns a RawPointer pointing to a physical lvalue. The returned pointer is
|
|
/// only valid for the duration of the original binding.
|
|
BUILTIN_SIL_OPERATION(AddressOf, "addressof", Special)
|
|
|
|
/// unprotectedAddressOf (inout T) -> Builtin.RawPointer
|
|
/// Returns a RawPointer pointing to a physical lvalue. The returned pointer is
|
|
/// only valid for the duration of the original binding.
|
|
/// In contrast to `addressof`, this builtin doesn't trigger an insertion of
|
|
/// stack protectors.
|
|
BUILTIN_SIL_OPERATION(UnprotectedAddressOf, "unprotectedAddressOf", Special)
|
|
|
|
/// addressOfBorrow (__shared T) -> Builtin.RawPointer
|
|
/// Returns a RawPointer pointing to a borrowed rvalue. The returned pointer is only
|
|
/// valid within the scope of the borrow.
|
|
BUILTIN_SIL_OPERATION(AddressOfBorrow, "addressOfBorrow", Special)
|
|
|
|
/// unprotectedAddressOfBorrow (__shared T) -> Builtin.RawPointer
|
|
/// Returns a RawPointer pointing to a borrowed rvalue. The returned pointer is only
|
|
/// valid within the scope of the borrow.
|
|
/// In contrast to `addressOfBorrow`, this builtin doesn't trigger an insertion of
|
|
/// stack protectors.
|
|
BUILTIN_SIL_OPERATION(UnprotectedAddressOfBorrow, "unprotectedAddressOfBorrow", Special)
|
|
|
|
/// GepRaw(Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer
|
|
///
|
|
/// Adds index bytes to a base pointer.
|
|
BUILTIN_SIL_OPERATION(GepRaw, "gepRaw", Integer)
|
|
|
|
/// Gep (Builtin.RawPointer, Builtin.Word, T.Type) -> Builtin.RawPointer
|
|
///
|
|
/// Like the GepRaw-builtin, but multiplies the index by stride-of type 'T'.
|
|
BUILTIN_SIL_OPERATION(Gep, "gep", Integer)
|
|
|
|
/// getTailAddr(Builtin.RawPointer,
|
|
/// Builtin.Word, T.Type, E.Type) -> Builtin.RawPointer
|
|
///
|
|
/// Like the Gep-builtin, but rounds up the resulting address to a tail-
|
|
/// allocated element type 'E'.
|
|
BUILTIN_SIL_OPERATION(GetTailAddr, "getTailAddr", Integer)
|
|
|
|
/// performInstantaneousReadAccess(Builtin.RawPointer, T.Type) -> ()
|
|
/// Begin and then immediately end a read access to the given raw pointer,
|
|
/// which will be treated as an address of type 'T'.
|
|
BUILTIN_SIL_OPERATION(PerformInstantaneousReadAccess,
|
|
"performInstantaneousReadAccess", Special)
|
|
|
|
/// beginUnpairedModifyAccess(Builtin.RawPointer, Builtin.RawPointer,
|
|
/// T.Type) -> ()
|
|
/// Begins but does not end a 'modify' access to the first raw pointer argument.
|
|
/// The second raw pointer must be a pointer to an UnsafeValueBuffer, which
|
|
/// will be used by the runtime to record the access. The lifetime of the
|
|
/// value buffer must be longer than that of the access itself. The accessed
|
|
/// address will be treated as having type 'T'.
|
|
BUILTIN_SIL_OPERATION(BeginUnpairedModifyAccess, "beginUnpairedModifyAccess",
|
|
Special)
|
|
|
|
/// endUnpairedAccess(Builtin.RawPointer) -> ()
|
|
/// Ends an in-progress unpaired access. The raw pointer argument must be
|
|
/// be a pointer to an UnsafeValueBuffer that records an in progress access.
|
|
BUILTIN_SIL_OPERATION(EndUnpairedAccess, "endUnpairedAccess", Special)
|
|
|
|
/// condfail(Int1) -> ()
|
|
/// Triggers a runtime failure if the condition is true.
|
|
/// This builtin is deprecated. Use condfail_message instead.
|
|
BUILTIN_SIL_OPERATION(LegacyCondFail, "condfail", Special)
|
|
|
|
/// fixLifetime(T) -> ()
|
|
/// Fixes the lifetime of any heap references in a value.
|
|
BUILTIN_SIL_OPERATION(FixLifetime, "fixLifetime", Special)
|
|
|
|
/// isUnique : <T> (inout T[?]) -> Int1
|
|
///
|
|
/// This builtin takes an inout object reference and returns a boolean. Passing
|
|
/// the reference inout forces the optimizer to preserve a retain distinct from
|
|
/// what's required to maintain lifetime for any of the reference's source-level
|
|
/// copies, because the called function is allowed to replace the reference,
|
|
/// thereby releasing the referent.
|
|
///
|
|
/// The kind of reference count checking that Builtin.isUnique performs depends
|
|
/// on the argument type:
|
|
///
|
|
/// - Native object types are directly checked by reading the
|
|
/// strong reference count:
|
|
/// (Builtin.NativeObject, known native class reference)
|
|
///
|
|
/// - Objective-C object types require an additional check that the
|
|
/// dynamic object type uses native swift reference counting:
|
|
/// (AnyObject, unknown class reference, class existential)
|
|
///
|
|
/// - Bridged object types allow the dynamic object type check to be
|
|
/// passed based on their pointer encoding:
|
|
/// (Builtin.BridgeObject)
|
|
///
|
|
/// Any of the above types may also be wrapped in an optional.
|
|
/// If the static argument type is optional, then a null check is also
|
|
/// performed.
|
|
///
|
|
/// Thus, isUnique only returns true for non-null, native swift object
|
|
/// references with a strong reference count of one.
|
|
BUILTIN_SIL_OPERATION(IsUnique, "isUnique", Special)
|
|
|
|
/// IsUnique_native : <T> (inout T[?]) -> Int1
|
|
///
|
|
/// These variants of isUnique implicitly cast to a non-null NativeObject before
|
|
/// checking uniqueness. This allows an object reference statically typed as
|
|
/// BridgeObject to be treated as a native object by the runtime.
|
|
BUILTIN_SIL_OPERATION(IsUnique_native, "isUnique_native", Special)
|
|
|
|
/// beginCOWMutation<T : AnyObject>(inout T) -> Int1
|
|
///
|
|
/// Begins a copy-on-write mutation for a buffer reference which is passed as
|
|
/// inout argument. It returns a true if the buffer is uniquely referenced.
|
|
/// In this case the buffer may be mutated after calling this builtin.
|
|
///
|
|
/// The beginCOWMutation builtin is very similar to isUnique. It just translates
|
|
/// to a different SIL instruction (begin_cow_mutation), which is the preferred
|
|
/// representation of COW in SIL.
|
|
BUILTIN_SIL_OPERATION(BeginCOWMutation, "beginCOWMutation", Special)
|
|
|
|
/// beginCOWMutation_native<T : AnyObject>(inout T) -> Int1
|
|
///
|
|
/// Like beginCOWMutation, but it's assumed that T has native Swift reference
|
|
/// counting.
|
|
BUILTIN_SIL_OPERATION(BeginCOWMutation_native, "beginCOWMutation_native", Special)
|
|
|
|
/// endCOWMutation<T : AnyObject>(inout T)
|
|
///
|
|
/// Ends a copy-on-write mutation for a buffer reference which is passed as
|
|
/// inout argument. After calling this builtin, the buffer must not be mutated.
|
|
BUILTIN_SIL_OPERATION(EndCOWMutation, "endCOWMutation", Special)
|
|
|
|
/// bindMemory : <T> (Builtin.RawPointer, Builtin.Word, T.Type) -> Builtin.Word
|
|
///
|
|
/// Binds memory to a statically known type. Returns an opaque token
|
|
/// representing the memory region's previously bound types.
|
|
BUILTIN_SIL_OPERATION(BindMemory, "bindMemory", Special)
|
|
|
|
/// rebindMemory : (Builtin.RawPointer, Builtin.Word) -> Builtin.Word
|
|
///
|
|
/// Binds memory to the types represented by an opaque token operand. Returns an
|
|
/// opaque token representing the memory region's previously bound types.
|
|
BUILTIN_SIL_OPERATION(RebindMemory, "rebindMemory", Special)
|
|
|
|
/// allocWithTailElems_<n>(C.Type,
|
|
/// Builtin.Word, E1.Type, ... , Builtin.Word, En.Type) -> C\
|
|
///
|
|
/// The integer suffix <n> specifies the number of tail-allocated arrays.
|
|
/// Each tail-allocated array adds a counter and an element meta-type parameter.
|
|
BUILTIN_SIL_OPERATION(AllocWithTailElems, "allocWithTailElems", Special)
|
|
|
|
/// projectTailElems : <C,E> (C) -> Builtin.RawPointer
|
|
///
|
|
/// Projects the first tail-allocated element of type E from a class C.
|
|
BUILTIN_SIL_OPERATION(ProjectTailElems, "projectTailElems", Special)
|
|
|
|
/// Unsafely convert a value of type T to an unowned value.
|
|
///
|
|
/// It has type (T, @inout @unowned(unsafe) T) -> (). The reason for the weird
|
|
/// signature is to work around issues with results in SILGen builtin emission.
|
|
BUILTIN_SIL_OPERATION(ConvertStrongToUnownedUnsafe, "convertStrongToUnownedUnsafe", Special)
|
|
|
|
/// Unsafely convert a value of type @inout @unowned(unsafe) T to a loaded
|
|
/// guaranteed T value that has a lifetime guaranteed by the passed in base
|
|
/// value of type BaseTy.
|
|
///
|
|
/// It has type (@in_guaranteed BaseTy, @in_guaranteed @unowned (unsafe) T) -> @guaranteed T.
|
|
///
|
|
/// NOTE: Saying the result is a guaranteed T is a bit of a misnomer. We aren't
|
|
/// emitting a builtin call, but are just emitting SIL directly.
|
|
///
|
|
/// NOTE: Even though the signature is as mentioned above, we actually tell the
|
|
/// AST we have the signature:
|
|
///
|
|
/// <BaseT, T, U> (BaseT, T) -> U
|
|
///
|
|
/// We then perform the actual type checking in SILGen and assert on
|
|
/// failure. This is an early, unsupported feature so this is sufficient for
|
|
/// now.
|
|
BUILTIN_SIL_OPERATION(ConvertUnownedUnsafeToGuaranteed, "convertUnownedUnsafeToGuaranteed", Special)
|
|
|
|
/// applyDerivative
|
|
BUILTIN_SIL_OPERATION(ApplyDerivative, "applyDerivative", Special)
|
|
|
|
/// applyTranspose
|
|
BUILTIN_SIL_OPERATION(ApplyTranspose, "applyTranspose", Special)
|
|
|
|
/// withUnsafeContinuation<T> : (Builtin.RawUnsafeContinuation -> ()) async -> sending T
|
|
///
|
|
/// Unsafely capture the current continuation and pass it to the given
|
|
/// function value. Returns a value of type T when the continuation is
|
|
/// resumed.
|
|
BUILTIN_SIL_OPERATION(WithUnsafeContinuation, "withUnsafeContinuation", Special)
|
|
|
|
/// withUnsafeThrowingContinuation<T> : (Builtin.RawUnsafeContinuation -> ()) async throws -> sending T
|
|
///
|
|
/// Unsafely capture the current continuation and pass it to the given
|
|
/// function value. Returns a value of type T or throws an error when
|
|
/// the continuation is resumed.
|
|
BUILTIN_SIL_OPERATION(WithUnsafeThrowingContinuation, "withUnsafeThrowingContinuation", Special)
|
|
|
|
/// Force the current task to be rescheduled on the specified actor.
|
|
BUILTIN_SIL_OPERATION(HopToActor, "hopToActor", None)
|
|
|
|
/// packLength: <each T>(_: repeat each T) -> Int
|
|
///
|
|
/// Returns the number of items in a pack.
|
|
BUILTIN_SIL_OPERATION(PackLength, "packLength", Special)
|
|
|
|
// BUILTIN_RUNTIME_CALL - A call into a runtime function.
|
|
// These functions accept a single argument of any type.
|
|
#ifndef BUILTIN_RUNTIME_CALL
|
|
#define BUILTIN_RUNTIME_CALL(Id, Name, Attrs) \
|
|
BUILTIN(Id, Name, Attrs)
|
|
#endif
|
|
|
|
/// unexpectedError: Error -> ()
|
|
BUILTIN_RUNTIME_CALL(UnexpectedError, "unexpectedError", "")
|
|
|
|
/// errorInMain: Error -> ()
|
|
BUILTIN_RUNTIME_CALL(ErrorInMain, "errorInMain", "")
|
|
|
|
/// IsOptionalType : T.Type -> Bool
|
|
/// This builtin takes a metatype and returns true if the metatype's
|
|
/// nominal type is Optional.
|
|
BUILTIN_RUNTIME_CALL(IsOptionalType, "isOptional", "")
|
|
|
|
// BUILTIN_MISC_OPERATION - Miscellaneous operations without a unifying class.
|
|
// These have various types.
|
|
#ifndef BUILTIN_MISC_OPERATION
|
|
#define BUILTIN_MISC_OPERATION(Id, Name, Attrs, Overload) \
|
|
BUILTIN(Id, Name, Attrs)
|
|
#endif
|
|
|
|
/// condfail_message(Int1, RawPointer) -> ()
|
|
/// Triggers a runtime failure if the condition is true.
|
|
BUILTIN_MISC_OPERATION(CondFailMessage, "condfail_message", "", Special)
|
|
|
|
/// IsPOD has type T.Type -> Bool
|
|
BUILTIN_MISC_OPERATION(IsPOD, "ispod", "n", Special)
|
|
|
|
/// IsConcrete has type (T.Type) -> Bool
|
|
///
|
|
/// If the meta type T is concrete, we can always transform this to `true` at
|
|
/// any time in SIL. If it's generic, then we lower it to `false` right before
|
|
/// IRGen in IRGenPrepare. This allows for the optimizer to specialize this at
|
|
/// -O and eliminate conditional code.
|
|
BUILTIN_MISC_OPERATION(IsConcrete, "isConcrete", "n", Special)
|
|
|
|
/// IsBitwiseTakable has type T.Type -> Bool
|
|
BUILTIN_MISC_OPERATION(IsBitwiseTakable, "isbitwisetakable", "n", Special)
|
|
|
|
/// IsSameMetatype has type
|
|
/// (any (~Copyable & ~Escapable).Type, any (~Copyable & ~Escapable).Type) -> Bool
|
|
BUILTIN_MISC_OPERATION(IsSameMetatype, "is_same_metatype", "n", Special)
|
|
|
|
/// AllocRaw has type (Int, Int) -> Builtin.RawPointer
|
|
///
|
|
/// Parameters: object size, object alignment.
|
|
///
|
|
/// This alignment is not a mask; the compiler decrements by one to provide
|
|
/// a mask to the runtime.
|
|
///
|
|
/// If alignment == 0, then the runtime will use "aligned" allocation,
|
|
/// and the memory will be aligned to _swift_MinAllocationAlignment.
|
|
BUILTIN_MISC_OPERATION(AllocRaw, "allocRaw", "", Special)
|
|
|
|
/// DeallocRaw has type (Builtin.RawPointer, Int, Int) -> ()
|
|
///
|
|
/// Parameters: object address, object size, object alignment.
|
|
///
|
|
/// This alignment is not a mask; the compiler decrements by one to provide
|
|
/// a mask to the runtime.
|
|
///
|
|
/// If alignment == 0, then the runtime will use the "aligned" deallocation
|
|
/// path, which assumes that "aligned" allocation was used.
|
|
///
|
|
/// Note that the alignment value provided to `deallocRaw` must be identical to
|
|
/// the alignment value provided to `allocRaw` when the memory at this address
|
|
/// was allocated.
|
|
BUILTIN_MISC_OPERATION(DeallocRaw, "deallocRaw", "", Special)
|
|
|
|
/// StackAlloc has type (Int, Int, Int) -> Builtin.RawPointer
|
|
///
|
|
/// Parameters: capacity, stride, alignment
|
|
///
|
|
/// The resulting pointer comes from the stack (as in the non-standard C
|
|
/// extension `alloca()`.) It is at least as aligned as specified and is valid
|
|
/// until the end of the calling scope.
|
|
///
|
|
/// The count and stride are multiplied together to get the byte count to use
|
|
/// for the allocation.
|
|
///
|
|
/// The passed alignment must be a positive power of two. If the alignment value
|
|
/// is not known at compile time, MaximumAlignment is assumed.
|
|
BUILTIN_MISC_OPERATION(StackAlloc, "stackAlloc", "", Special)
|
|
|
|
/// Like `stackAlloc`, but doesn't set the `[stack_protection]` flag on its
|
|
/// containing function.
|
|
BUILTIN_MISC_OPERATION(UnprotectedStackAlloc, "unprotectedStackAlloc", "", Special)
|
|
|
|
/// StackDealloc has type (Builtin.RawPointer) -> ()
|
|
///
|
|
/// Parameters: address.
|
|
///
|
|
/// The range starting at `address`, previously allocated with
|
|
/// Builtin.stackAlloc(), is deallocated from the stack.
|
|
BUILTIN_MISC_OPERATION(StackDealloc, "stackDealloc", "", Special)
|
|
|
|
// Obsolete: only there to be able to read old Swift.interface files which still
|
|
// contain the builtin.
|
|
/// allocVector<Element>(Element.Type, Builtin.Word) -> Builtin.RawPointer
|
|
BUILTIN_MISC_OPERATION(AllocVector, "allocVector", "", Special)
|
|
|
|
/// Fence has type () -> ().
|
|
BUILTIN_MISC_OPERATION(Fence, "fence", "", None)
|
|
|
|
/// onFastPath has type () -> ().
|
|
BUILTIN_MISC_OPERATION(OnFastPath, "onFastPath", "n", None)
|
|
|
|
/// CmpXChg has type (Builtin.RawPointer, T, T) -> (T, Bool).
|
|
BUILTIN_MISC_OPERATION(CmpXChg, "cmpxchg", "", Special)
|
|
|
|
/// AtomicLoad has type (Builtin.RawPointer) -> T.
|
|
BUILTIN_MISC_OPERATION(AtomicLoad, "atomicload", "", Special)
|
|
|
|
/// AtomicStore has type (Builtin.RawPointer, T) -> ().
|
|
BUILTIN_MISC_OPERATION(AtomicStore, "atomicstore", "", Special)
|
|
|
|
/// AtomicRMW has type (Builtin.RawPointer, T) -> T.
|
|
BUILTIN_MISC_OPERATION(AtomicRMW, "atomicrmw", "", IntegerOrRawPointer)
|
|
|
|
/// convertTaskToJob : (Builtin.NativePointer) -> Builtin.Job
|
|
///
|
|
/// Convert a task pointer into a job pointer.
|
|
BUILTIN_MISC_OPERATION(ConvertTaskToJob, "convertTaskToJob", "n", Special)
|
|
|
|
/// ExtractElement has type (Vector<N, T>, Int32) -> T
|
|
BUILTIN_MISC_OPERATION(ExtractElement, "extractelement", "n", Special)
|
|
|
|
/// InsertElement has type (Vector<N, T>, T, Int32) -> Vector<N, T>.
|
|
BUILTIN_MISC_OPERATION(InsertElement, "insertelement", "n", Special)
|
|
|
|
/// Select has type either
|
|
/// (VecN<Int1>, VecN<T>, VecN<T>) -> VecN<T>
|
|
/// or
|
|
/// (Int1, T, T) -> T
|
|
/// T must be trivial.
|
|
BUILTIN_MISC_OPERATION(Select, "select", "n", Special)
|
|
|
|
/// Shufflevector has type (VecN<T>, VecN<T>, VecM<Int32>) -> VecM<T>
|
|
BUILTIN_MISC_OPERATION(ShuffleVector, "shufflevector", "n", Special)
|
|
|
|
/// Interleave has type (VecN<T>, VecN<T>) -> (VecN<T>, VecN<T>)
|
|
BUILTIN_MISC_OPERATION(Interleave, "interleave", "n", Special)
|
|
|
|
/// Deinterleave has type (VecN<T>, VecN<T>) -> (VecN<T>, VecN<T>)
|
|
BUILTIN_MISC_OPERATION(Deinterleave, "deinterleave", "n", Special)
|
|
|
|
/// StaticReport has type (Builtin.Int1, Builtin.Int1, Builtin.RawPointer) -> ()
|
|
BUILTIN_MISC_OPERATION(StaticReport, "staticReport", "", Special)
|
|
|
|
/// assert_configuration has type () -> Builtin.Int32
|
|
/// Returns the selected assertion configuration.
|
|
BUILTIN_MISC_OPERATION(AssertConf, "assert_configuration", "n", Special)
|
|
|
|
/// Ifdef has type () -> Bool.
|
|
BUILTIN_MISC_OPERATION(Ifdef, "ifdef", "n", Special)
|
|
|
|
/// StringObjectOr has type (T,T) -> T.
|
|
/// Sets bits in a string object. The first operand is bit-cast string literal
|
|
/// pointer to an integer. The second operand is the bit mask to be or'd into
|
|
/// the high bits of the pointer.
|
|
/// It is required that the or'd bits are all 0 in the first operand. So this
|
|
/// or-operation is actually equivalent to an addition.
|
|
BUILTIN_MISC_OPERATION(StringObjectOr, "stringObjectOr", "n", Integer)
|
|
|
|
/// Special truncation builtins that check for sign and overflow errors. These
|
|
/// take an integer as an input and return a tuple of the truncated result and
|
|
/// an error bit. The name of each builtin is extended with the "from"
|
|
/// (sign-agnostic) builtin integer type and the "to" integer type.
|
|
/// We require the source type size to be larger than the destination type size
|
|
/// (number of bits).
|
|
BUILTIN_MISC_OPERATION(UToSCheckedTrunc, "u_to_s_checked_trunc", "n", Special)
|
|
BUILTIN_MISC_OPERATION(SToSCheckedTrunc, "s_to_s_checked_trunc", "n", Special)
|
|
BUILTIN_MISC_OPERATION(SToUCheckedTrunc, "s_to_u_checked_trunc", "n", Special)
|
|
BUILTIN_MISC_OPERATION(UToUCheckedTrunc, "u_to_u_checked_trunc", "n", Special)
|
|
|
|
/// IntToFPWithOverflow has type (Integer) -> Float
|
|
BUILTIN_MISC_OPERATION(IntToFPWithOverflow, "itofp_with_overflow", "n", Special)
|
|
|
|
/// Builtin.bitWidth_IntLiteral has type
|
|
/// (_ value: Builtin.IntLiteral) -> Builtin.Word
|
|
BUILTIN_MISC_OPERATION(BitWidth, "bitWidth", "n", Special)
|
|
|
|
/// Builtin.isNegative_IntLiteral has type
|
|
/// (_ value: Builtin.IntLiteral) -> Builtin.Int1
|
|
BUILTIN_MISC_OPERATION(IsNegative, "isNegative", "n", Special)
|
|
|
|
/// Builtin.wordAtIndex_IntLiteral has type
|
|
/// (_ value: Builtin.IntLiteral, _ index: Builtin.Word) -> Builtin.Word
|
|
BUILTIN_MISC_OPERATION(WordAtIndex, "wordAtIndex", "n", Special)
|
|
|
|
/// once has type (Builtin.RawPointer, (Builtin.RawPointer) -> ())
|
|
BUILTIN_MISC_OPERATION(Once, "once", "", Special)
|
|
/// onceWithContext has type (Builtin.RawPointer, (Builtin.RawPointer) -> (), Builtin.RawPointer)
|
|
BUILTIN_MISC_OPERATION(OnceWithContext, "onceWithContext", "", Special)
|
|
|
|
/// unreachable has type () -> Never
|
|
BUILTIN_MISC_OPERATION(Unreachable, "unreachable", "", Special)
|
|
|
|
/// conditionallyUnreachable has type () -> Never
|
|
BUILTIN_MISC_OPERATION(CondUnreachable, "conditionallyUnreachable", "", Special)
|
|
|
|
/// DestroyArray has type (T.Type, Builtin.RawPointer, Builtin.Word) -> ()
|
|
BUILTIN_MISC_OPERATION(DestroyArray, "destroyArray", "", Special)
|
|
|
|
/// CopyArray, TakeArrayNoAlias, TakeArrayFrontToBack, and TakeArrayBackToFront
|
|
/// AssignCopyArrayNoAlias, AssignCopyArrayFrontToBack,
|
|
/// AssignCopyArrayBackToFront, AssignTakeArray all have type
|
|
/// (T.Type, Builtin.RawPointer, Builtin.RawPointer, Builtin.Word) -> ()
|
|
BUILTIN_MISC_OPERATION(CopyArray, "copyArray", "", Special)
|
|
BUILTIN_MISC_OPERATION(TakeArrayNoAlias, "takeArrayNoAlias", "", Special)
|
|
BUILTIN_MISC_OPERATION(TakeArrayFrontToBack, "takeArrayFrontToBack", "", Special)
|
|
BUILTIN_MISC_OPERATION(TakeArrayBackToFront, "takeArrayBackToFront", "", Special)
|
|
BUILTIN_MISC_OPERATION(AssignCopyArrayNoAlias, "assignCopyArrayNoAlias", "", Special)
|
|
BUILTIN_MISC_OPERATION(AssignCopyArrayFrontToBack, "assignCopyArrayFrontToBack", "", Special)
|
|
BUILTIN_MISC_OPERATION(AssignCopyArrayBackToFront, "assignCopyArrayBackToFront", "", Special)
|
|
BUILTIN_MISC_OPERATION(AssignTakeArray, "assignTakeArray", "", Special)
|
|
|
|
/// COWBufferForReading has type <T: AnyObject> T -> T
|
|
///
|
|
/// Returns the buffer reference which is passed as argument.
|
|
/// This builtin indicates to the optimizer that the buffer is not mutable.
|
|
BUILTIN_MISC_OPERATION(COWBufferForReading, "COWBufferForReading", "n", Special)
|
|
|
|
// getObjCTypeEncoding has type <T> T.Type -> RawPointer
|
|
BUILTIN_MISC_OPERATION(GetObjCTypeEncoding, "getObjCTypeEncoding", "n", Special)
|
|
|
|
/// willThrow: Error -> ()
|
|
BUILTIN_MISC_OPERATION(WillThrow, "willThrow", "", Special)
|
|
|
|
/// poundAssert has type (Builtin.Int1, Builtin.RawPointer) -> ().
|
|
BUILTIN_MISC_OPERATION(PoundAssert, "poundAssert", "", Special)
|
|
|
|
// TypePtrAuthDiscriminator has type <T> (T.Type) -> Int64
|
|
BUILTIN_MISC_OPERATION(TypePtrAuthDiscriminator, "typePtrAuthDiscriminator", "n", Special)
|
|
|
|
/// Initialize the default-actor instance in a default actor object.
|
|
BUILTIN_MISC_OPERATION(InitializeDefaultActor, "initializeDefaultActor", "", Special)
|
|
|
|
/// Destroy the default-actor instance in a default actor object.
|
|
BUILTIN_MISC_OPERATION(DestroyDefaultActor, "destroyDefaultActor", "", Special)
|
|
|
|
/// Initialize the extra storage state of a non-default distributed actor object.
|
|
BUILTIN_MISC_OPERATION(InitializeNonDefaultDistributedActor,
|
|
"initializeNonDefaultDistributedActor", "", Special)
|
|
|
|
/// Allocate a "proxy" for a distributed remote actor.
|
|
BUILTIN_MISC_OPERATION(InitializeDistributedRemoteActor,
|
|
"initializeDistributedRemoteActor", "", Special)
|
|
|
|
/// Resume a non-throwing continuation normally with the given result.
|
|
BUILTIN_MISC_OPERATION(ResumeNonThrowingContinuationReturning,
|
|
"resumeNonThrowingContinuationReturning", "", Special)
|
|
|
|
/// targetOSVersionAtLeast has type (Builtin.Int32, Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
BUILTIN_MISC_OPERATION(TargetOSVersionAtLeast, "targetOSVersionAtLeast", "n", Special)
|
|
|
|
/// targetVariantOSVersionAtLeast has type (Builtin.Int32, Builtin.Int32, Builtin.Int32) -> Builtin.Int32
|
|
BUILTIN_MISC_OPERATION(TargetVariantOSVersionAtLeast, "targetVariantOSVersionAtLeast", "n", Special)
|
|
|
|
/// targetOSVersionOrVariantOSVersionAtLeast has type (Builtin.UInt32, Builtin.UInt32, Builtin.UInt32, Builtin.UInt32, Builtin.UInt32, Builtin.UInt32) -> Builtin.UInt32
|
|
BUILTIN_MISC_OPERATION(TargetOSVersionOrVariantOSVersionAtLeast, "targetOSVersionOrVariantOSVersionAtLeast", "n", Special)
|
|
|
|
/// Resume a throwing continuation normally with the given result.
|
|
BUILTIN_MISC_OPERATION(ResumeThrowingContinuationReturning,
|
|
"resumeThrowingContinuationReturning", "", Special)
|
|
|
|
/// Resume a throwing continuation abnormally with the given error.
|
|
BUILTIN_MISC_OPERATION(ResumeThrowingContinuationThrowing,
|
|
"resumeThrowingContinuationThrowing", "", Special)
|
|
|
|
/// Unchecked pointer alignment assertion. Allows the compiler to assume
|
|
/// alignment of the pointer to emit more efficient code.
|
|
///
|
|
/// %alignedPtr = builtin "assumeAlignment" (%ptr : $Builtin.RawPointer,
|
|
/// %alignment : $Builtin.Int)
|
|
/// : $Builtin.RawPointer
|
|
/// %address = pointer_to_address %alignedPtr
|
|
/// : $Builtin.RawPointer to [align=1] $*Int
|
|
/// %val = load %address : $*Int
|
|
///
|
|
/// With compile-time knowledge of the value of `%alignment` the compiler can
|
|
/// optimize any downstream 'pointer_to_address' instruction by refining its
|
|
/// '[align=]' flag . That `[align=]` flag can be used by IRGen to refine the
|
|
/// alignment on LLVM load instructions that use the resulting address.
|
|
///
|
|
/// (Builtin.RawPointer, Builtin.Word) -> Builtin.RawPointer
|
|
BUILTIN_MISC_OPERATION(AssumeAlignment, "assumeAlignment", "n", Special)
|
|
|
|
// BUILTIN_MISC_OPERATION_WITH_SILGEN - Miscellaneous operations that are
|
|
// specially emitted during SIL generation.
|
|
//
|
|
// The intention is that this is meant for builtins that need a named
|
|
// builtin representation so one can create a builtin instruction in
|
|
// SIL, but that also need special SILGen behavior. If an operation
|
|
// just emits custom SIL and does not need to be able to form a
|
|
// builtin instruction, please use BUILTIN_SIL_OPERATION.
|
|
#ifndef BUILTIN_MISC_OPERATION_WITH_SILGEN
|
|
#define BUILTIN_MISC_OPERATION_WITH_SILGEN(Id, Name, Attrs, Overload) \
|
|
BUILTIN_MISC_OPERATION(Id, Name, Attrs, Overload)
|
|
#endif
|
|
|
|
/// Sizeof has type T.Type -> Int
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(Sizeof, "sizeof", "n", Special)
|
|
|
|
/// Strideof has type T.Type -> Int
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(Strideof, "strideof", "n", Special)
|
|
|
|
/// Alignof has type T.Type -> Int
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(Alignof, "alignof", "n", Special)
|
|
|
|
/// zeroInitializer has type <T> () -> T, but the SIL builtin has its
|
|
/// own rules.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(ZeroInitializer, "zeroInitializer", "n", Special)
|
|
|
|
/// Like `zeroInitializer`, but does not actually initialize the memory.
|
|
/// It only indicates to mandatory passes that the memory is going to be initialized.
|
|
BUILTIN_MISC_OPERATION(PrepareInitialization, "prepareInitialization", "n", Special)
|
|
|
|
// getCurrentExecutor: () async -> Builtin.Executor?
|
|
//
|
|
// Retrieve the SerialExecutorRef on which the current asynchronous
|
|
// function is executing, or nil if the function isn't running
|
|
// anywhere in particular.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(GetCurrentExecutor, "getCurrentExecutor", "", Special)
|
|
|
|
// getCurrentAsyncTask: () -> Builtin.NativeObject
|
|
//
|
|
// Retrieve the pointer to the task in which the current asynchronous
|
|
// function is executing.
|
|
//
|
|
// This is readnone because, within the world modeled by SIL, the
|
|
// current async task of a thread never changes.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(GetCurrentAsyncTask, "getCurrentAsyncTask", "n", Special)
|
|
|
|
/// cancelAsyncTask(): (Builtin.NativeObject) -> Void
|
|
///
|
|
/// Cancel the given asynchronous task.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(CancelAsyncTask, "cancelAsyncTask", "", Special)
|
|
|
|
/// startAsyncLet()<T>: (
|
|
/// __owned @escaping () async throws -> sending T
|
|
/// ) -> Builtin.RawPointer
|
|
///
|
|
/// DEPRECATED. startAsyncLetWithLocalBuffer is used instead.
|
|
///
|
|
/// Create, initialize and start a new async-let and associated task.
|
|
/// Returns an AsyncLet* that must be passed to endAsyncLet for destruction.
|
|
BUILTIN_MISC_OPERATION(StartAsyncLet, "startAsyncLet", "", Special)
|
|
|
|
/// startAsyncLetWithLocalBuffer()<T>: (
|
|
/// __owned @escaping () async throws -> sending T,
|
|
/// _ resultBuf: Builtin.RawPointer
|
|
/// ) -> Builtin.RawPointer
|
|
///
|
|
/// Create, initialize and start a new async-let and associated task, with a
|
|
/// locally-allocated buffer assigned to receive the result if the task
|
|
/// completes.
|
|
/// Returns an AsyncLet* that must be passed to endAsyncLetLifetime for
|
|
/// destruction.
|
|
BUILTIN_MISC_OPERATION(StartAsyncLetWithLocalBuffer, "startAsyncLetWithLocalBuffer", "", Special)
|
|
|
|
/// taskRunInline()<T>: (
|
|
/// () async -> T
|
|
/// ) -> T
|
|
///
|
|
/// Create an async context inline in the current synchronous context and run
|
|
/// the specified closure.
|
|
///
|
|
/// This is only supported under the task-to-thread concurrency model.
|
|
BUILTIN_MISC_OPERATION(TaskRunInline, "taskRunInline", "", Special)
|
|
|
|
/// flowSensitiveSelfIsolation<T: Actor>(_ actor: T) -> (any Actor)?
|
|
///
|
|
/// Used only in actor initializers, this builtin lowers to either 'actor'
|
|
/// (wrapped in an optional) or 'nil' depending on whether 'self' has been
|
|
/// initialized at this point. 'actor' is always an alias for the 'self'
|
|
/// being initialized.
|
|
BUILTIN_MISC_OPERATION(FlowSensitiveSelfIsolation, "flowSensitiveSelfIsolation", "", Special)
|
|
|
|
/// flowSensitiveDistributedSelfIsolation<T: DistributedActor>(
|
|
/// _ actor: T
|
|
/// ) -> (any Actor)?
|
|
///
|
|
/// Used only in distributed actor initializers, this builtin lowers to either
|
|
/// 'actor.asLocalActor' or 'nil' depending on whether 'self' has been
|
|
/// initialized at this point. 'actor' is always an alias for the 'self'
|
|
/// being initialized.
|
|
BUILTIN_MISC_OPERATION(FlowSensitiveDistributedSelfIsolation,
|
|
"flowSensitiveDistributedSelfIsolation", "", Special)
|
|
|
|
/// endAsyncLet(): (Builtin.RawPointer) -> Void
|
|
///
|
|
/// DEPRECATED. The swift_asyncLet_finish intrinsic and endAsyncLetLifetime
|
|
/// builtin are used instead.
|
|
///
|
|
/// Ends and destroys an async-let.
|
|
/// The ClosureLifetimeFixup pass adds a second operand to the builtin to
|
|
/// ensure that optimizations keep the stack-allocated closure arguments alive
|
|
/// until the endAsyncLet.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(EndAsyncLet, "endAsyncLet", "", Special)
|
|
|
|
/// endAsyncLetLifetime(): (Builtin.RawPointer) -> Void
|
|
///
|
|
/// Marks the end of an async-let's lifetime.
|
|
/// The ClosureLifetimeFixup pass adds a second operand to the builtin to
|
|
/// ensure that optimizations keep the stack-allocated closure arguments alive
|
|
/// until the endAsyncLet.
|
|
BUILTIN_MISC_OPERATION(EndAsyncLetLifetime, "endAsyncLetLifetime", "", Special)
|
|
|
|
/// addressOfBorrowOpaque (__shared T) -> Builtin.RawPointer
|
|
/// Returns a RawPointer pointing to a borrowed rvalue. The returned pointer is
|
|
/// only valid within the scope of the borrow.
|
|
///
|
|
/// Differs from addressOfBorrow only in that it is not lowered until
|
|
/// AddressLowering.
|
|
BUILTIN_MISC_OPERATION(AddressOfBorrowOpaque, "addressOfBorrowOpaque", "", Special)
|
|
|
|
/// unprotectedAddressOfBorrowOpaque (__shared T) -> Builtin.RawPointer
|
|
/// Returns a RawPointer pointing to a borrowed rvalue. The returned pointer is only
|
|
/// valid within the scope of the borrow.
|
|
/// In contrast to `addressOfBorrowOpaque`, this builtin doesn't trigger an
|
|
/// insertion of stack protectors.
|
|
///
|
|
/// Differs from unprotectedAddressOfBorrow only in that it is not lowered until
|
|
/// AddressLowering.
|
|
BUILTIN_MISC_OPERATION(UnprotectedAddressOfBorrowOpaque, "unprotectedAddressOfBorrowOpaque", "", Special)
|
|
|
|
/// createTask<T>(flags: Int,
|
|
/// initialSerialExecutor: (Builtin.Executor)? = nil,
|
|
/// taskGroup: Builtin.RawPointer? = nil,
|
|
/// initialTaskExecutorDeprecated: (Builtin.Executor)? = nil,
|
|
/// initialTaskExecutorOwned: (any TaskExecutor)? = nil,
|
|
/// operation: sending @escaping () async throws -> T)
|
|
/// -> Builtin.NativeObject, Builtin.RawPointer)
|
|
///
|
|
/// Create a new task.
|
|
BUILTIN_SIL_OPERATION(CreateTask, "createTask", Special)
|
|
|
|
/// createDiscardingTask(flags: Int,
|
|
/// initialSerialExecutor: (Builtin.Executor)? = nil,
|
|
/// taskGroup: Builtin.RawPointer? = nil,
|
|
/// initialTaskExecutor: (Builtin.Executor)? = nil,
|
|
/// operation: sending @escaping () async throws -> ())
|
|
/// -> (Builtin.NativeObject, Builtin.RawPointer)
|
|
///
|
|
/// Create a new discarding task.
|
|
BUILTIN_SIL_OPERATION(CreateDiscardingTask, "createDiscardingTask", Special)
|
|
|
|
/// createAsyncTask(): (
|
|
/// Int, // task-creation flags
|
|
/// sending @escaping () async throws -> T // function
|
|
/// ) -> Builtin.NativeObject
|
|
///
|
|
/// Legacy spelling of:
|
|
/// createTask(flags: $0, operation: $1)
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateAsyncTask,
|
|
"createAsyncTask", "", Special)
|
|
|
|
/// createAsyncTaskInGroup(): (
|
|
/// Int, // flags
|
|
/// Builtin.RawPointer, // group
|
|
/// sending @escaping () async throws -> T // function
|
|
/// ) -> Builtin.NativeObject
|
|
///
|
|
/// Legacy spelling of:
|
|
/// createTask(flags: $0, taskGroup: $1, operation: $2)
|
|
BUILTIN_SIL_OPERATION(CreateAsyncTaskInGroup,
|
|
"createAsyncTaskInGroup", Special)
|
|
|
|
/// createAsyncDiscardingTaskInGroup(): (
|
|
/// Int, // flags
|
|
/// Builtin.RawPointer, // group
|
|
/// sending @escaping () async throws -> Void // function
|
|
/// ) -> Builtin.NativeObject
|
|
///
|
|
/// Legacy spelling of:
|
|
/// createDiscardingTask(flags: $0, taskGroup: $1, operation: $2)
|
|
BUILTIN_SIL_OPERATION(CreateAsyncDiscardingTaskInGroup,
|
|
"createAsyncDiscardingTaskInGroup", Special)
|
|
|
|
/// createAsyncTaskWithExecutor(): (
|
|
/// Int, // flags
|
|
/// Builtin.Executor, // executor
|
|
/// sending @escaping () async throws -> T // function
|
|
/// ) -> Builtin.NativeObject
|
|
///
|
|
/// Legacy spelling of:
|
|
/// createTask(flags: $0, initialTaskExecutor: $1, operation: $2)
|
|
BUILTIN_SIL_OPERATION(CreateAsyncTaskWithExecutor,
|
|
"createAsyncTaskWithExecutor", Special)
|
|
|
|
/// createAsyncTaskInGroupWithExecutor(): (
|
|
/// Int, // flags
|
|
/// Builtin.RawPointer, // group
|
|
/// Builtin.Executor, // executor
|
|
/// sending @escaping () async throws -> T // function
|
|
/// ) -> Builtin.NativeObject
|
|
///
|
|
/// Legacy spelling of:
|
|
/// createTask(flags: $0, taskGroup: $1, initialTaskExecutor: $2, operation: $3)
|
|
BUILTIN_SIL_OPERATION(CreateAsyncTaskInGroupWithExecutor,
|
|
"createAsyncTaskInGroupWithExecutor", Special)
|
|
|
|
/// createAsyncDiscardingTaskInGroupWithExecutor(): (
|
|
/// Int, // flags
|
|
/// Builtin.RawPointer, // group
|
|
/// Builtin.Executor, // executor
|
|
/// sending @escaping () async throws -> Void // function
|
|
/// ) -> Builtin.NativeObject
|
|
///
|
|
/// Legacy spelling of:
|
|
/// createDiscardingTask(flags: $0, taskGroup: $1, initialTaskExecutor: $2,
|
|
/// operation: $3)
|
|
BUILTIN_SIL_OPERATION(CreateAsyncDiscardingTaskInGroupWithExecutor,
|
|
"createAsyncDiscardingTaskInGroupWithExecutor", Special)
|
|
|
|
/// Build a Builtin.Executor value from an "ordinary" task executor
|
|
/// reference.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildOrdinaryTaskExecutorRef,
|
|
"buildOrdinaryTaskExecutorRef", "n", Special)
|
|
|
|
/// Create a task group.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateTaskGroup, "createTaskGroup", "", Special)
|
|
|
|
/// Create a task group, with options.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(CreateTaskGroupWithFlags, "createTaskGroupWithFlags", "", Special)
|
|
|
|
/// Destroy a task group.
|
|
BUILTIN_MISC_OPERATION(DestroyTaskGroup, "destroyTaskGroup", "", Special)
|
|
|
|
/// globalStringTablePointer has type String -> Builtin.RawPointer.
|
|
/// It returns an immortal, global string table pointer for strings constructed
|
|
/// from string literals. We consider it effects as readnone meaning that it
|
|
/// does not read any memory (note that even though it reads from a string, it
|
|
/// is a pure value and therefore we can consider it as readnone).
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(GlobalStringTablePointer, "globalStringTablePointer", "n", Special)
|
|
|
|
// autoDiffCreateLinearMapContextWithType: (T.Type) -> Builtin.NativeObject
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(AutoDiffCreateLinearMapContextWithType, "autoDiffCreateLinearMapContextWithType", "", Special)
|
|
|
|
// autoDiffProjectTopLevelSubcontext: (Builtin.NativeObject) -> Builtin.RawPointer
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(AutoDiffProjectTopLevelSubcontext, "autoDiffProjectTopLevelSubcontext", "n", Special)
|
|
|
|
// autoDiffAllocateSubcontextWithType: (Builtin.NativeObject, T.Type) -> Builtin.RawPointer
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(AutoDiffAllocateSubcontextWithType, "autoDiffAllocateSubcontextWithType", "", Special)
|
|
|
|
/// Build a Builtin.Executor value from an "ordinary" serial executor
|
|
/// reference.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildOrdinarySerialExecutorRef,
|
|
"buildOrdinarySerialExecutorRef", "n", Special)
|
|
|
|
/// Build a Builtin.Executor value from an "complex equality" serial executor
|
|
/// reference.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildComplexEqualitySerialExecutorRef,
|
|
"buildComplexEqualitySerialExecutorRef", "n", Special)
|
|
|
|
/// Build a Builtin.Executor value from a default actor reference.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildDefaultActorExecutorRef,
|
|
"buildDefaultActorExecutorRef", "n", Special)
|
|
|
|
/// Build a Builtin.Executor value for the main actor.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(BuildMainActorExecutorRef,
|
|
"buildMainActorExecutorRef", "n", Special)
|
|
|
|
/// extractFunctionIsolation: <T>(_: T) -> (any Actor)?
|
|
///
|
|
/// Returns the isolation of a value, which must be an @isolated(any)
|
|
/// function type.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(ExtractFunctionIsolation,
|
|
"extractFunctionIsolation", "", Special)
|
|
|
|
/// getEnumTag: <T>(_: T) -> Builtin.Int32
|
|
///
|
|
/// Given a dynamic generic value, unsafely assume it is an enum type and call
|
|
/// the getEnumTag vwt function.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(GetEnumTag, "getEnumTag", "", Special)
|
|
|
|
/// injectEnumTag: <T>(_: inout T, _: Builtin.Int32) -> ()
|
|
///
|
|
/// Given a dynamic inout generic value, unsafely assume it is an enum type and
|
|
/// inject the given tag into it.
|
|
///
|
|
/// Note: This assume that either 1. the given tag has no payload or 2. the
|
|
/// tag's payload is already initialized with the given source.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(InjectEnumTag, "injectEnumTag", "", Special)
|
|
|
|
/// distributedActorAsAnyActor: <DA: DistributedActor>(_: DA) -> any Actor
|
|
///
|
|
/// For a given distributed actor that is known to be local, extract an
|
|
/// `any Actor` existential that refers to the local actor.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(DistributedActorAsAnyActor, "distributedActorAsAnyActor", "n", Special)
|
|
|
|
/// addressOfRawLayout: <T: ~Copyable>(_: borrowing T) -> Builtin.RawPointer
|
|
///
|
|
/// Returns a raw pointer to the address of the raw layout type. This address is
|
|
/// only valid during a borrow access of the raw layout type or until the value
|
|
/// is either moved or consumed.
|
|
///
|
|
/// Note: The purpose of this builtin is to get an opaque pointer to the address
|
|
/// of the raw layout type. We explicitly do not want the optimizer looking into
|
|
/// this pointer or address thereof to start assuming things about mutability or
|
|
/// immutability. This builtin _must_ persist throughout all of SIL and must be
|
|
/// lowered away at IRGen, no sooner.
|
|
BUILTIN_MISC_OPERATION_WITH_SILGEN(AddressOfRawLayout, "addressOfRawLayout", "n", Special)
|
|
|
|
/// emplace<T>((Builtin.RawPointer) -> Void) -> T
|
|
///
|
|
/// Passes a pointer to an uninitialized result value to the given function,
|
|
/// which must initialize the memory before finishing execution. The value in
|
|
/// memory becomes the result of the call.
|
|
BUILTIN_SIL_OPERATION(Emplace, "emplace", Special)
|
|
|
|
/// Builtins for instrumentation added by sanitizers during SILGen.
|
|
#ifndef BUILTIN_SANITIZER_OPERATION
|
|
#define BUILTIN_SANITIZER_OPERATION(Id, Name, Attrs) BUILTIN(Id, Name, Attrs)
|
|
#endif
|
|
|
|
/// Builtin representing a call to Thread Sanitizer instrumentation.
|
|
/// TSanInoutAccess has type (T) -> ()
|
|
BUILTIN_SANITIZER_OPERATION(TSanInoutAccess, "tsanInoutAccess", "")
|
|
|
|
/// Builtins for compile-time type-checking operations used for unit testing.
|
|
#ifndef BUILTIN_TYPE_CHECKER_OPERATION
|
|
#define BUILTIN_TYPE_CHECKER_OPERATION(Id, Name) BUILTIN(Id, #Name, "n")
|
|
#endif
|
|
|
|
BUILTIN_TYPE_CHECKER_OPERATION(TypeJoin, type_join)
|
|
BUILTIN_TYPE_CHECKER_OPERATION(TypeJoinInout, type_join_inout)
|
|
BUILTIN_TYPE_CHECKER_OPERATION(TypeJoinMeta, type_join_meta)
|
|
BUILTIN_TYPE_CHECKER_OPERATION(TriggerFallbackDiagnostic, trigger_fallback_diagnostic)
|
|
|
|
// BUILTIN_TYPE_TRAIT_OPERATION - Compile-time type trait operations.
|
|
#ifndef BUILTIN_TYPE_TRAIT_OPERATION
|
|
#define BUILTIN_TYPE_TRAIT_OPERATION(Id, Name) \
|
|
BUILTIN(Id, #Name, "n")
|
|
#endif
|
|
|
|
/// canBeClass(T.Type) -> Builtin.Int8
|
|
/// At compile time, evaluate whether T is or can be bound to a class or
|
|
/// @objc protocol type. The answer is a tri-state of 0 = No, 1 = Yes, 2 =
|
|
/// Maybe.
|
|
BUILTIN_TYPE_TRAIT_OPERATION(CanBeObjCClass, canBeClass)
|
|
|
|
#undef BUILTIN_TYPE_TRAIT_OPERATION
|
|
#undef BUILTIN_UNARY_OPERATION
|
|
#undef BUILTIN_BINARY_PREDICATE
|
|
#undef BUILTIN_RUNTIME_CALL
|
|
#undef BUILTIN_MISC_OPERATION_WITH_SILGEN
|
|
#undef BUILTIN_MISC_OPERATION
|
|
#undef BUILTIN_SANITIZER_OPERATION
|
|
#undef BUILTIN_TYPE_CHECKER_OPERATION
|
|
#undef BUILTIN_BINARY_OPERATION_WITH_OVERFLOW
|
|
#undef BUILTIN_BINARY_OPERATION_ALL
|
|
#undef BUILTIN_BINARY_OPERATION_POLYMORPHIC
|
|
#undef BUILTIN_BINARY_OPERATION_OVERLOADED_STATIC
|
|
#undef BUILTIN_BINARY_OPERATION_GENERIC_HELPER_STR
|
|
#undef BUILTIN_BINARY_OPERATION
|
|
#undef BUILTIN_CAST_OPERATION
|
|
#undef BUILTIN_CAST_OR_BITCAST_OPERATION
|
|
#undef BUILTIN_SIL_OPERATION
|
|
#undef BUILTIN
|