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:
Joe Groff
2014-04-09 00:37:26 +00:00
parent e9d2e122ee
commit 8adaab0233
35 changed files with 505 additions and 339 deletions

View File

@@ -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,

View File

@@ -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();
}

View File

@@ -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,

View File

@@ -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.

View File

@@ -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