Skip to content

Commit 8adaab0

Browse files
committed
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
1 parent e9d2e12 commit 8adaab0

35 files changed

+506
-340
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -981,6 +981,8 @@ ERROR(first_class_generic_function,type_parsing,PointsToFirstBadToken,
981981
"generic types cannot be used as first-class types", ())
982982
ERROR(autoclosure_function_input_nonunit,attribute_parsing,none,
983983
"auto_closure argument type must be '()'", ())
984+
ERROR(objc_block_cannot_be_thin,attribute_parsing,none,
985+
"@objc_block function type cannot be @thin", ())
984986

985987
// SIL
986988
ERROR(sil_local_storage_nested, decl_parsing,none,

include/swift/AST/Types.h

Lines changed: 52 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,21 +1702,33 @@ class AnyFunctionType : public TypeBase {
17021702
const Type Output;
17031703

17041704
public:
1705+
/// \brief The representation form of a function.
1706+
enum class Representation {
1707+
// A "thick" function that carries a context pointer to reference captured
1708+
// state. The default.
1709+
Thick = 0,
1710+
1711+
// A thick function that is represented as an Objective-C block.
1712+
Block,
1713+
1714+
// A "thin" function that needs no context.
1715+
Thin,
1716+
};
1717+
17051718
/// \brief A class which abstracts out some details necessary for
17061719
/// making a call.
17071720
class ExtInfo {
17081721
// Feel free to rearrange or add bits, but if you go over 7,
17091722
// you'll need to adjust both the Bits field below and
17101723
// BaseType::AnyFunctionTypeBits.
17111724

1712-
// | CC |isThin|isAutoClosure|isBlock|noReturn|
1713-
// |0 .. 3| 4 | 5 | 6 | 7 |
1725+
// | CC |representation|isAutoClosure|noReturn|
1726+
// |0 .. 3| 4 .. 5 | 6 | 7 |
17141727
//
1715-
enum { CallConvMask = 0xF };
1716-
enum { ThinMask = 0x10 };
1717-
enum { AutoClosureMask = 0x20 };
1718-
enum { BlockMask = 0x40 };
1719-
enum { NoReturnMask = 0x80 };
1728+
enum : uint16_t { CallConvMask = 0xF };
1729+
enum : uint16_t { RepresentationMask = 0x30, RepresentationShift = 4 };
1730+
enum : uint16_t { AutoClosureMask = 0x40 };
1731+
enum : uint16_t { NoReturnMask = 0x80 };
17201732

17211733
uint16_t Bits;
17221734

@@ -1732,40 +1744,49 @@ class AnyFunctionType : public TypeBase {
17321744
}
17331745

17341746
// Constructor for polymorphic type.
1735-
ExtInfo(AbstractCC CC, bool IsThin, bool IsNoReturn) {
1747+
ExtInfo(AbstractCC CC, Representation Rep, bool IsNoReturn) {
17361748
Bits = ((unsigned) CC) |
1737-
(IsThin ? ThinMask : 0) |
1749+
((unsigned) Rep << RepresentationShift) |
17381750
(IsNoReturn ? NoReturnMask : 0);
17391751
}
17401752

17411753
// Constructor with no defaults.
1742-
ExtInfo(AbstractCC CC, bool IsThin, bool IsNoReturn,
1743-
bool IsAutoClosure, bool IsBlock) : ExtInfo(CC, IsThin, IsNoReturn){
1754+
ExtInfo(AbstractCC CC, Representation Rep, bool IsNoReturn,
1755+
bool IsAutoClosure) : ExtInfo(CC, Rep, IsNoReturn){
17441756
Bits = Bits |
1745-
(IsAutoClosure ? AutoClosureMask : 0) |
1746-
(IsBlock ? BlockMask : 0);
1757+
(IsAutoClosure ? AutoClosureMask : 0);
17471758
}
17481759

17491760
explicit ExtInfo(AbstractCC CC) : Bits(0) {
17501761
Bits = (Bits & ~CallConvMask) | (unsigned) CC;
17511762
}
17521763

17531764
AbstractCC getCC() const { return AbstractCC(Bits & CallConvMask); }
1754-
bool isThin() const { return Bits & ThinMask; }
17551765
bool isNoReturn() const { return Bits & NoReturnMask; }
17561766
bool isAutoClosure() const { return Bits & AutoClosureMask; }
1757-
bool isBlock() const { return Bits & BlockMask; }
1758-
1767+
Representation getRepresentation() const {
1768+
return Representation((Bits & RepresentationMask) >> RepresentationShift);
1769+
}
1770+
1771+
/// True if the function representation carries context.
1772+
bool hasContext() const {
1773+
switch (getRepresentation()) {
1774+
case Representation::Thick:
1775+
case Representation::Block:
1776+
return true;
1777+
case Representation::Thin:
1778+
return false;
1779+
}
1780+
}
1781+
17591782
// Note that we don't have setters. That is by design, use
17601783
// the following with methods instead of mutating these objects.
17611784
ExtInfo withCallingConv(AbstractCC CC) const {
17621785
return ExtInfo((Bits & ~CallConvMask) | (unsigned) CC);
17631786
}
1764-
ExtInfo withIsThin(bool IsThin) const {
1765-
if (IsThin)
1766-
return ExtInfo(Bits | ThinMask);
1767-
else
1768-
return ExtInfo(Bits & ~ThinMask);
1787+
ExtInfo withRepresentation(Representation Rep) const {
1788+
return ExtInfo((Bits & ~RepresentationMask)
1789+
| (unsigned)Rep << RepresentationShift);
17691790
}
17701791
ExtInfo withIsNoReturn(bool IsNoReturn) const {
17711792
if (IsNoReturn)
@@ -1779,13 +1800,7 @@ class AnyFunctionType : public TypeBase {
17791800
else
17801801
return ExtInfo(Bits & ~AutoClosureMask);
17811802
}
1782-
ExtInfo withIsBlock(bool IsBlock) const {
1783-
if (IsBlock)
1784-
return ExtInfo(Bits | BlockMask);
1785-
else
1786-
return ExtInfo(Bits & ~BlockMask);
1787-
}
1788-
1803+
17891804
char getFuncAttrKey() const {
17901805
return Bits;
17911806
}
@@ -1820,12 +1835,11 @@ class AnyFunctionType : public TypeBase {
18201835
return getExtInfo().getCC();
18211836
}
18221837

1823-
/// \brief True if the function type is "thin", meaning values of the type can
1824-
/// be represented as simple function pointers without context.
1825-
bool isThin() const {
1826-
return getExtInfo().isThin();
1838+
/// \brief Get the representation of the function type.
1839+
Representation getRepresentation() const {
1840+
return getExtInfo().getRepresentation();
18271841
}
1828-
1842+
18291843
bool isNoReturn() const {
18301844
return getExtInfo().isNoReturn();
18311845
}
@@ -1836,11 +1850,6 @@ class AnyFunctionType : public TypeBase {
18361850
return getExtInfo().isAutoClosure();
18371851
}
18381852

1839-
/// \brief True if this type is an Objective-C-compatible block type.
1840-
bool isBlock() const {
1841-
return getExtInfo().isBlock();
1842-
}
1843-
18441853
// Implement isa/cast/dyncast/etc.
18451854
static bool classof(const TypeBase *T) {
18461855
return T->getKind() >= TypeKind::First_AnyFunctionType &&
@@ -2263,7 +2272,8 @@ typedef CanTypeWrapper<SILFunctionType> CanSILFunctionType;
22632272
class SILFunctionType : public TypeBase, public llvm::FoldingSetNode {
22642273
public:
22652274
typedef AnyFunctionType::ExtInfo ExtInfo;
2266-
2275+
typedef AnyFunctionType::Representation Representation;
2276+
22672277
private:
22682278
CanGenericSignature GenericSig;
22692279

@@ -2360,17 +2370,11 @@ class SILFunctionType : public TypeBase, public llvm::FoldingSetNode {
23602370
return getExtInfo().getCC();
23612371
}
23622372

2363-
/// \brief True if this type is an Objective-C-compatible block type.
2364-
bool isBlock() const {
2365-
return getExtInfo().isBlock();
2373+
/// \brief Get the representation of the function type.
2374+
Representation getRepresentation() const {
2375+
return getExtInfo().getRepresentation();
23662376
}
23672377

2368-
/// \brief True if the function type is "thin", meaning values of the type can
2369-
/// be represented as simple function pointers without context.
2370-
bool isThin() const {
2371-
return getExtInfo().isThin();
2372-
}
2373-
23742378
bool isNoReturn() const {
23752379
return getExtInfo().isNoReturn();
23762380
}

include/swift/SIL/SILBuilder.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -710,10 +710,9 @@ class SILBuilder {
710710
ASTContext &AST = F.getModule().getASTContext();
711711
// builtin_function_ref "int_trap" : $@thin @noreturn () -> ()
712712
auto bfrInfo = SILFunctionType::ExtInfo(AbstractCC::Freestanding,
713-
/*thin*/ true,
714-
/*noreturn*/ true,
715-
/*autoclosure*/ false,
716-
/*block*/ false);
713+
SILFunctionType::Representation::Thin,
714+
/*noreturn*/ true,
715+
/*autoclosure*/ false);
717716
SILResultInfo Result(TupleType::getEmpty(AST), ResultConvention::Unowned);
718717
auto bfrFnType = SILFunctionType::get(nullptr, bfrInfo,
719718
ParameterConvention::Direct_Owned,

include/swift/SIL/TypeLowering.h

Lines changed: 20 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,30 +41,20 @@ const ParameterConvention DefaultThickCalleeConvention =
4141
CanAnyFunctionType adjustFunctionType(CanAnyFunctionType type,
4242
AnyFunctionType::ExtInfo extInfo);
4343

44-
/// Make the given function type @thin and change its CC.
45-
inline CanAnyFunctionType getThinFunctionType(CanAnyFunctionType t,
46-
AbstractCC cc) {
47-
auto extInfo = t->getExtInfo().withIsThin(true).withCallingConv(cc);
44+
/// Change the given function type's representation and CC.
45+
inline CanAnyFunctionType adjustFunctionType(CanAnyFunctionType t,
46+
AbstractCC cc,
47+
AnyFunctionType::Representation rep) {
48+
auto extInfo = t->getExtInfo().withRepresentation(rep).withCallingConv(cc);
4849
return adjustFunctionType(t, extInfo);
4950
}
50-
/// Make the given function type @thin.
51-
inline CanAnyFunctionType getThinFunctionType(CanAnyFunctionType t) {
52-
auto extInfo = t->getExtInfo().withIsThin(true);
51+
/// Change the given function type's representation.
52+
inline CanAnyFunctionType adjustFunctionType(CanAnyFunctionType t,
53+
AnyFunctionType::Representation rep) {
54+
auto extInfo = t->getExtInfo().withRepresentation(rep);
5355
return adjustFunctionType(t, extInfo);
5456
}
55-
56-
/// Make the given function type no longer @thin and change its CC.
57-
inline CanAnyFunctionType getThickFunctionType(CanAnyFunctionType t,
58-
AbstractCC cc) {
59-
auto extInfo = t->getExtInfo().withIsThin(false).withCallingConv(cc);
60-
return adjustFunctionType(t, extInfo);
61-
}
62-
/// Make the given function type no longer @thin.
63-
inline CanAnyFunctionType getThickFunctionType(CanAnyFunctionType t) {
64-
auto extInfo = t->getExtInfo().withIsThin(false);
65-
return adjustFunctionType(t, extInfo);
66-
}
67-
57+
6858
/// Given a SIL function type, return a type that is identical except
6959
/// for using the given ExtInfo.
7060
CanSILFunctionType adjustFunctionType(CanSILFunctionType type,
@@ -74,17 +64,16 @@ inline CanSILFunctionType adjustFunctionType(CanSILFunctionType type,
7464
SILFunctionType::ExtInfo extInfo) {
7565
return adjustFunctionType(type, extInfo, type->getCalleeConvention());
7666
}
77-
inline CanSILFunctionType getThinFunctionType(CanSILFunctionType t) {
78-
if (t->isThin()) return t;
79-
return adjustFunctionType(t, t->getExtInfo().withIsThin(true),
80-
ParameterConvention::Direct_Unowned);
81-
}
82-
inline CanSILFunctionType getThickFunctionType(CanSILFunctionType t) {
83-
if (!t->isThin()) return t;
84-
return adjustFunctionType(t, t->getExtInfo().withIsThin(false),
85-
DefaultThickCalleeConvention);
67+
inline CanSILFunctionType adjustFunctionType(CanSILFunctionType t,
68+
SILFunctionType::Representation rep) {
69+
if (t->getRepresentation() == rep) return t;
70+
auto extInfo = t->getExtInfo().withRepresentation(rep);
71+
72+
return adjustFunctionType(t, extInfo,
73+
extInfo.hasContext() ? DefaultThickCalleeConvention
74+
: ParameterConvention::Direct_Unowned);
8675
}
87-
76+
8877
/// Different ways in which a function can capture context.
8978
enum class CaptureKind {
9079
/// No context arguments are necessary.
@@ -618,7 +607,7 @@ class TypeConverter {
618607
CanSILFunctionType getConstantFunctionType(SILDeclRef constant,
619608
CanAnyFunctionType substFormalType,
620609
CanAnyFunctionType substFormalInterfaceType,
621-
bool thin);
610+
AnyFunctionType::Representation rep);
622611

623612
/// Substitute the given function type so that it implements the
624613
/// given substituted type.

include/swift/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const uint16_t VERSION_MAJOR = 0;
4040
/// Serialized module format minor version number.
4141
///
4242
/// When the format changes IN ANY WAY, this number should be incremented.
43-
const uint16_t VERSION_MINOR = 46;
43+
const uint16_t VERSION_MINOR = 49;
4444

4545
using DeclID = Fixnum<31>;
4646
using DeclIDField = BCFixed<31>;
@@ -531,6 +531,7 @@ namespace decls_block {
531531
ParameterConventionField, // callee convention
532532
AbstractCCField, // calling convention
533533
BCFixed<1>, // thin?
534+
BCFixed<1>, // block?
534535
BCFixed<1>, // noreturn?
535536
BCFixed<30>, // number of generic parameters
536537
BCArray<TypeIDField> // parameter types and conventions, alternating

lib/AST/ASTPrinter.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1695,11 +1695,18 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
16951695
Printer << "@cc(witness_method) ";
16961696
break;
16971697
}
1698-
1699-
if (info.isBlock())
1700-
Printer << "@objc_block ";
1701-
if (info.isThin())
1698+
1699+
switch (info.getRepresentation()) {
1700+
case AnyFunctionType::Representation::Thick:
1701+
break;
1702+
case AnyFunctionType::Representation::Thin:
17021703
Printer << "@thin ";
1704+
break;
1705+
case AnyFunctionType::Representation::Block:
1706+
Printer << "@objc_block ";
1707+
break;
1708+
}
1709+
17031710
if (info.isNoReturn())
17041711
Printer << "@noreturn ";
17051712
}

lib/AST/Decl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1779,7 +1779,7 @@ bool AbstractStorageDecl::usesObjCGetterAndSetter() const {
17791779
// blocks.
17801780
if (isa<VarDecl>(this)) {
17811781
if (auto ft = getType()->getAs<AnyFunctionType>())
1782-
return ft->isBlock();
1782+
return ft->getRepresentation() == AnyFunctionType::Representation::Block;
17831783
}
17841784

17851785
return true;

lib/AST/Mangle.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -823,14 +823,14 @@ void Mangler::mangleType(CanType type, ResilienceExpansion explosion,
823823
};
824824

825825
// <impl-callee-convention>
826-
if (fn->isThin()) {
826+
if (fn->getRepresentation() == AnyFunctionType::Representation::Thin) {
827827
Buffer << 't';
828828
} else {
829829
Buffer << mangleParameterConvention(fn->getCalleeConvention());
830830
}
831831

832832
// <impl-function-attribute>*
833-
if (fn->isBlock()) {
833+
if (fn->getRepresentation() == AnyFunctionType::Representation::Block) {
834834
Buffer << "Cb";
835835
} else {
836836
switch (fn->getAbstractCC()) {
@@ -1149,7 +1149,7 @@ void Mangler::mangleFunctionType(CanAnyFunctionType fn,
11491149
// type ::= 'f' type type (uncurried)
11501150
// type ::= 'b' type type (objc block)
11511151
// type ::= 'K' type type (auto closure)
1152-
if (fn->isBlock())
1152+
if (fn->getRepresentation() == AnyFunctionType::Representation::Block)
11531153
Buffer << 'b';
11541154
else if (fn->isAutoClosure())
11551155
Buffer << 'K';

lib/AST/Type.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,9 +1121,7 @@ bool TypeBase::isSpelledLike(Type other) {
11211121
auto fThem = cast<FunctionType>(them);
11221122
if (fMe->isAutoClosure() != fThem->isAutoClosure())
11231123
return false;
1124-
if (fMe->isBlock() != fThem->isBlock())
1125-
return false;
1126-
if (fMe->isThin() != fThem->isThin())
1124+
if (fMe->getRepresentation() != fThem->getRepresentation())
11271125
return false;
11281126
if (fMe->isNoReturn() != fThem->isNoReturn())
11291127
return false;
@@ -1285,9 +1283,11 @@ static bool hasRetainablePointerRepresentation(CanType type) {
12851283

12861284
// Blocks.
12871285
if (auto fnType = dyn_cast<AnyFunctionType>(type)) {
1288-
return fnType->isBlock();
1286+
return fnType->getRepresentation()
1287+
== AnyFunctionType::Representation::Block;
12891288
} else if (auto fnType = dyn_cast<SILFunctionType>(type)) {
1290-
return fnType->isBlock();
1289+
return fnType->getRepresentation()
1290+
== AnyFunctionType::Representation::Block;
12911291
}
12921292

12931293
// Class metatypes.

lib/ClangImporter/ImportType.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,8 @@ namespace {
231231
return Type();
232232
FunctionType *fTy = pointeeType->castTo<FunctionType>();
233233
return FunctionType::get(fTy->getInput(), fTy->getResult(),
234-
fTy->getExtInfo().withIsBlock(true));
234+
fTy->getExtInfo()
235+
.withRepresentation(AnyFunctionType::Representation::Block));
235236
}
236237

237238
Type VisitReferenceType(const clang::ReferenceType *type) {

0 commit comments

Comments
 (0)