mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Fold ExtInfo::isThin and ::isBlock into a "Representation" enum.
These bits are orthogonal to each other, so combine them into one, and diagnose attempts to produce a type that's both. Spot-fix a bunch of places this revealed by inspection that we would have crashed in SILGen or IRGen if blocks were be handled. Swift SVN r16088
This commit is contained in:
@@ -981,6 +981,8 @@ ERROR(first_class_generic_function,type_parsing,PointsToFirstBadToken,
|
||||
"generic types cannot be used as first-class types", ())
|
||||
ERROR(autoclosure_function_input_nonunit,attribute_parsing,none,
|
||||
"auto_closure argument type must be '()'", ())
|
||||
ERROR(objc_block_cannot_be_thin,attribute_parsing,none,
|
||||
"@objc_block function type cannot be @thin", ())
|
||||
|
||||
// SIL
|
||||
ERROR(sil_local_storage_nested, decl_parsing,none,
|
||||
|
||||
@@ -1702,6 +1702,19 @@ class AnyFunctionType : public TypeBase {
|
||||
const Type Output;
|
||||
|
||||
public:
|
||||
/// \brief The representation form of a function.
|
||||
enum class Representation {
|
||||
// A "thick" function that carries a context pointer to reference captured
|
||||
// state. The default.
|
||||
Thick = 0,
|
||||
|
||||
// A thick function that is represented as an Objective-C block.
|
||||
Block,
|
||||
|
||||
// A "thin" function that needs no context.
|
||||
Thin,
|
||||
};
|
||||
|
||||
/// \brief A class which abstracts out some details necessary for
|
||||
/// making a call.
|
||||
class ExtInfo {
|
||||
@@ -1709,14 +1722,13 @@ public:
|
||||
// you'll need to adjust both the Bits field below and
|
||||
// BaseType::AnyFunctionTypeBits.
|
||||
|
||||
// | CC |isThin|isAutoClosure|isBlock|noReturn|
|
||||
// |0 .. 3| 4 | 5 | 6 | 7 |
|
||||
// | CC |representation|isAutoClosure|noReturn|
|
||||
// |0 .. 3| 4 .. 5 | 6 | 7 |
|
||||
//
|
||||
enum { CallConvMask = 0xF };
|
||||
enum { ThinMask = 0x10 };
|
||||
enum { AutoClosureMask = 0x20 };
|
||||
enum { BlockMask = 0x40 };
|
||||
enum { NoReturnMask = 0x80 };
|
||||
enum : uint16_t { CallConvMask = 0xF };
|
||||
enum : uint16_t { RepresentationMask = 0x30, RepresentationShift = 4 };
|
||||
enum : uint16_t { AutoClosureMask = 0x40 };
|
||||
enum : uint16_t { NoReturnMask = 0x80 };
|
||||
|
||||
uint16_t Bits;
|
||||
|
||||
@@ -1732,18 +1744,17 @@ public:
|
||||
}
|
||||
|
||||
// Constructor for polymorphic type.
|
||||
ExtInfo(AbstractCC CC, bool IsThin, bool IsNoReturn) {
|
||||
ExtInfo(AbstractCC CC, Representation Rep, bool IsNoReturn) {
|
||||
Bits = ((unsigned) CC) |
|
||||
(IsThin ? ThinMask : 0) |
|
||||
((unsigned) Rep << RepresentationShift) |
|
||||
(IsNoReturn ? NoReturnMask : 0);
|
||||
}
|
||||
|
||||
// Constructor with no defaults.
|
||||
ExtInfo(AbstractCC CC, bool IsThin, bool IsNoReturn,
|
||||
bool IsAutoClosure, bool IsBlock) : ExtInfo(CC, IsThin, IsNoReturn){
|
||||
ExtInfo(AbstractCC CC, Representation Rep, bool IsNoReturn,
|
||||
bool IsAutoClosure) : ExtInfo(CC, Rep, IsNoReturn){
|
||||
Bits = Bits |
|
||||
(IsAutoClosure ? AutoClosureMask : 0) |
|
||||
(IsBlock ? BlockMask : 0);
|
||||
(IsAutoClosure ? AutoClosureMask : 0);
|
||||
}
|
||||
|
||||
explicit ExtInfo(AbstractCC CC) : Bits(0) {
|
||||
@@ -1751,21 +1762,31 @@ public:
|
||||
}
|
||||
|
||||
AbstractCC getCC() const { return AbstractCC(Bits & CallConvMask); }
|
||||
bool isThin() const { return Bits & ThinMask; }
|
||||
bool isNoReturn() const { return Bits & NoReturnMask; }
|
||||
bool isAutoClosure() const { return Bits & AutoClosureMask; }
|
||||
bool isBlock() const { return Bits & BlockMask; }
|
||||
|
||||
Representation getRepresentation() const {
|
||||
return Representation((Bits & RepresentationMask) >> RepresentationShift);
|
||||
}
|
||||
|
||||
/// True if the function representation carries context.
|
||||
bool hasContext() const {
|
||||
switch (getRepresentation()) {
|
||||
case Representation::Thick:
|
||||
case Representation::Block:
|
||||
return true;
|
||||
case Representation::Thin:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we don't have setters. That is by design, use
|
||||
// the following with methods instead of mutating these objects.
|
||||
ExtInfo withCallingConv(AbstractCC CC) const {
|
||||
return ExtInfo((Bits & ~CallConvMask) | (unsigned) CC);
|
||||
}
|
||||
ExtInfo withIsThin(bool IsThin) const {
|
||||
if (IsThin)
|
||||
return ExtInfo(Bits | ThinMask);
|
||||
else
|
||||
return ExtInfo(Bits & ~ThinMask);
|
||||
ExtInfo withRepresentation(Representation Rep) const {
|
||||
return ExtInfo((Bits & ~RepresentationMask)
|
||||
| (unsigned)Rep << RepresentationShift);
|
||||
}
|
||||
ExtInfo withIsNoReturn(bool IsNoReturn) const {
|
||||
if (IsNoReturn)
|
||||
@@ -1779,13 +1800,7 @@ public:
|
||||
else
|
||||
return ExtInfo(Bits & ~AutoClosureMask);
|
||||
}
|
||||
ExtInfo withIsBlock(bool IsBlock) const {
|
||||
if (IsBlock)
|
||||
return ExtInfo(Bits | BlockMask);
|
||||
else
|
||||
return ExtInfo(Bits & ~BlockMask);
|
||||
}
|
||||
|
||||
|
||||
char getFuncAttrKey() const {
|
||||
return Bits;
|
||||
}
|
||||
@@ -1820,12 +1835,11 @@ public:
|
||||
return getExtInfo().getCC();
|
||||
}
|
||||
|
||||
/// \brief True if the function type is "thin", meaning values of the type can
|
||||
/// be represented as simple function pointers without context.
|
||||
bool isThin() const {
|
||||
return getExtInfo().isThin();
|
||||
/// \brief Get the representation of the function type.
|
||||
Representation getRepresentation() const {
|
||||
return getExtInfo().getRepresentation();
|
||||
}
|
||||
|
||||
|
||||
bool isNoReturn() const {
|
||||
return getExtInfo().isNoReturn();
|
||||
}
|
||||
@@ -1836,11 +1850,6 @@ public:
|
||||
return getExtInfo().isAutoClosure();
|
||||
}
|
||||
|
||||
/// \brief True if this type is an Objective-C-compatible block type.
|
||||
bool isBlock() const {
|
||||
return getExtInfo().isBlock();
|
||||
}
|
||||
|
||||
// Implement isa/cast/dyncast/etc.
|
||||
static bool classof(const TypeBase *T) {
|
||||
return T->getKind() >= TypeKind::First_AnyFunctionType &&
|
||||
@@ -2263,7 +2272,8 @@ typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType;
|
||||
class SILFunctionType : public TypeBase, public llvm::FoldingSetNode {
|
||||
public:
|
||||
typedef AnyFunctionType::ExtInfo ExtInfo;
|
||||
|
||||
typedef AnyFunctionType::Representation Representation;
|
||||
|
||||
private:
|
||||
CanGenericSignature GenericSig;
|
||||
|
||||
@@ -2360,17 +2370,11 @@ public:
|
||||
return getExtInfo().getCC();
|
||||
}
|
||||
|
||||
/// \brief True if this type is an Objective-C-compatible block type.
|
||||
bool isBlock() const {
|
||||
return getExtInfo().isBlock();
|
||||
/// \brief Get the representation of the function type.
|
||||
Representation getRepresentation() const {
|
||||
return getExtInfo().getRepresentation();
|
||||
}
|
||||
|
||||
/// \brief True if the function type is "thin", meaning values of the type can
|
||||
/// be represented as simple function pointers without context.
|
||||
bool isThin() const {
|
||||
return getExtInfo().isThin();
|
||||
}
|
||||
|
||||
bool isNoReturn() const {
|
||||
return getExtInfo().isNoReturn();
|
||||
}
|
||||
|
||||
@@ -710,10 +710,9 @@ public:
|
||||
ASTContext &AST = F.getModule().getASTContext();
|
||||
// builtin_function_ref "int_trap" : $@thin @noreturn () -> ()
|
||||
auto bfrInfo = SILFunctionType::ExtInfo(AbstractCC::Freestanding,
|
||||
/*thin*/ true,
|
||||
/*noreturn*/ true,
|
||||
/*autoclosure*/ false,
|
||||
/*block*/ false);
|
||||
SILFunctionType::Representation::Thin,
|
||||
/*noreturn*/ true,
|
||||
/*autoclosure*/ false);
|
||||
SILResultInfo Result(TupleType::getEmpty(AST), ResultConvention::Unowned);
|
||||
auto bfrFnType = SILFunctionType::get(nullptr, bfrInfo,
|
||||
ParameterConvention::Direct_Owned,
|
||||
|
||||
@@ -41,30 +41,20 @@ const ParameterConvention DefaultThickCalleeConvention =
|
||||
CanAnyFunctionType adjustFunctionType(CanAnyFunctionType type,
|
||||
AnyFunctionType::ExtInfo extInfo);
|
||||
|
||||
/// Make the given function type @thin and change its CC.
|
||||
inline CanAnyFunctionType getThinFunctionType(CanAnyFunctionType t,
|
||||
AbstractCC cc) {
|
||||
auto extInfo = t->getExtInfo().withIsThin(true).withCallingConv(cc);
|
||||
/// Change the given function type's representation and CC.
|
||||
inline CanAnyFunctionType adjustFunctionType(CanAnyFunctionType t,
|
||||
AbstractCC cc,
|
||||
AnyFunctionType::Representation rep) {
|
||||
auto extInfo = t->getExtInfo().withRepresentation(rep).withCallingConv(cc);
|
||||
return adjustFunctionType(t, extInfo);
|
||||
}
|
||||
/// Make the given function type @thin.
|
||||
inline CanAnyFunctionType getThinFunctionType(CanAnyFunctionType t) {
|
||||
auto extInfo = t->getExtInfo().withIsThin(true);
|
||||
/// Change the given function type's representation.
|
||||
inline CanAnyFunctionType adjustFunctionType(CanAnyFunctionType t,
|
||||
AnyFunctionType::Representation rep) {
|
||||
auto extInfo = t->getExtInfo().withRepresentation(rep);
|
||||
return adjustFunctionType(t, extInfo);
|
||||
}
|
||||
|
||||
/// Make the given function type no longer @thin and change its CC.
|
||||
inline CanAnyFunctionType getThickFunctionType(CanAnyFunctionType t,
|
||||
AbstractCC cc) {
|
||||
auto extInfo = t->getExtInfo().withIsThin(false).withCallingConv(cc);
|
||||
return adjustFunctionType(t, extInfo);
|
||||
}
|
||||
/// Make the given function type no longer @thin.
|
||||
inline CanAnyFunctionType getThickFunctionType(CanAnyFunctionType t) {
|
||||
auto extInfo = t->getExtInfo().withIsThin(false);
|
||||
return adjustFunctionType(t, extInfo);
|
||||
}
|
||||
|
||||
|
||||
/// Given a SIL function type, return a type that is identical except
|
||||
/// for using the given ExtInfo.
|
||||
CanSILFunctionType adjustFunctionType(CanSILFunctionType type,
|
||||
@@ -74,17 +64,16 @@ inline CanSILFunctionType adjustFunctionType(CanSILFunctionType type,
|
||||
SILFunctionType::ExtInfo extInfo) {
|
||||
return adjustFunctionType(type, extInfo, type->getCalleeConvention());
|
||||
}
|
||||
inline CanSILFunctionType getThinFunctionType(CanSILFunctionType t) {
|
||||
if (t->isThin()) return t;
|
||||
return adjustFunctionType(t, t->getExtInfo().withIsThin(true),
|
||||
ParameterConvention::Direct_Unowned);
|
||||
inline CanSILFunctionType adjustFunctionType(CanSILFunctionType t,
|
||||
SILFunctionType::Representation rep) {
|
||||
if (t->getRepresentation() == rep) return t;
|
||||
auto extInfo = t->getExtInfo().withRepresentation(rep);
|
||||
|
||||
return adjustFunctionType(t, extInfo,
|
||||
extInfo.hasContext() ? DefaultThickCalleeConvention
|
||||
: ParameterConvention::Direct_Unowned);
|
||||
}
|
||||
inline CanSILFunctionType getThickFunctionType(CanSILFunctionType t) {
|
||||
if (!t->isThin()) return t;
|
||||
return adjustFunctionType(t, t->getExtInfo().withIsThin(false),
|
||||
DefaultThickCalleeConvention);
|
||||
}
|
||||
|
||||
|
||||
/// Different ways in which a function can capture context.
|
||||
enum class CaptureKind {
|
||||
/// No context arguments are necessary.
|
||||
@@ -618,7 +607,7 @@ public:
|
||||
CanSILFunctionType getConstantFunctionType(SILDeclRef constant,
|
||||
CanAnyFunctionType substFormalType,
|
||||
CanAnyFunctionType substFormalInterfaceType,
|
||||
bool thin);
|
||||
AnyFunctionType::Representation rep);
|
||||
|
||||
/// Substitute the given function type so that it implements the
|
||||
/// given substituted type.
|
||||
|
||||
@@ -40,7 +40,7 @@ const uint16_t VERSION_MAJOR = 0;
|
||||
/// Serialized module format minor version number.
|
||||
///
|
||||
/// When the format changes IN ANY WAY, this number should be incremented.
|
||||
const uint16_t VERSION_MINOR = 46;
|
||||
const uint16_t VERSION_MINOR = 49;
|
||||
|
||||
using DeclID = Fixnum<31>;
|
||||
using DeclIDField = BCFixed<31>;
|
||||
@@ -531,6 +531,7 @@ namespace decls_block {
|
||||
ParameterConventionField, // callee convention
|
||||
AbstractCCField, // calling convention
|
||||
BCFixed<1>, // thin?
|
||||
BCFixed<1>, // block?
|
||||
BCFixed<1>, // noreturn?
|
||||
BCFixed<30>, // number of generic parameters
|
||||
BCArray<TypeIDField> // parameter types and conventions, alternating
|
||||
|
||||
Reference in New Issue
Block a user