Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 47 additions & 28 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerEmbeddedInt.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallBitVector.h"
Expand Down Expand Up @@ -347,10 +348,11 @@ class alignas(1 << TypeAlignInBits) TypeBase {
Flags : NumFlagBits
);

SWIFT_INLINE_BITFIELD_FULL(AnyFunctionType, TypeBase, NumAFTExtInfoBits+1+16,
SWIFT_INLINE_BITFIELD_FULL(AnyFunctionType, TypeBase, NumAFTExtInfoBits+1+1+16,
/// Extra information which affects how the function is called, like
/// regparm and the calling convention.
ExtInfoBits : NumAFTExtInfoBits,
HasExtInfo : 1,
HasClangTypeInfo : 1,
: NumPadBits,
NumParams : 16
Expand Down Expand Up @@ -2919,20 +2921,28 @@ class AnyFunctionType : public TypeBase {
///
/// Subclasses are responsible for storing and retrieving the
/// ClangTypeInfo value if one is present.
AnyFunctionType(TypeKind Kind, const ASTContext *CanTypeContext,
Type Output, RecursiveTypeProperties properties,
unsigned NumParams, ExtInfo Info)
: TypeBase(Kind, CanTypeContext, properties), Output(Output) {
Bits.AnyFunctionType.ExtInfoBits = Info.getBits();
Bits.AnyFunctionType.HasClangTypeInfo = !Info.getClangTypeInfo().empty();
AnyFunctionType(TypeKind Kind, const ASTContext *CanTypeContext, Type Output,
RecursiveTypeProperties properties, unsigned NumParams,
Optional<ExtInfo> Info)
: TypeBase(Kind, CanTypeContext, properties), Output(Output) {
if (Info.hasValue()) {
Bits.AnyFunctionType.HasExtInfo = true;
Bits.AnyFunctionType.ExtInfoBits = Info.getValue().getBits();
Bits.AnyFunctionType.HasClangTypeInfo =
!Info.getValue().getClangTypeInfo().empty();
// The use of both assert() and static_assert() is intentional.
assert(Bits.AnyFunctionType.ExtInfoBits == Info.getValue().getBits() &&
"Bits were dropped!");
static_assert(
ASTExtInfoBuilder::NumMaskBits == NumAFTExtInfoBits,
"ExtInfo and AnyFunctionTypeBitfields must agree on bit size");
} else {
Bits.AnyFunctionType.HasExtInfo = false;
Bits.AnyFunctionType.HasClangTypeInfo = false;
Bits.AnyFunctionType.ExtInfoBits = 0;
}
Bits.AnyFunctionType.NumParams = NumParams;
assert(Bits.AnyFunctionType.NumParams == NumParams && "Params dropped!");
// The use of both assert() and static_assert() is intentional.
assert(Bits.AnyFunctionType.ExtInfoBits == Info.getBits() &&
"Bits were dropped!");
static_assert(
ASTExtInfoBuilder::NumMaskBits == NumAFTExtInfoBits,
"ExtInfo and AnyFunctionTypeBitfields must agree on bit size");
}

public:
Expand Down Expand Up @@ -2993,7 +3003,10 @@ class AnyFunctionType : public TypeBase {
/// outer function type's mangling doesn't need to duplicate that information.
bool hasNonDerivableClangType();

bool hasExtInfo() const { return Bits.AnyFunctionType.HasExtInfo; }

ExtInfo getExtInfo() const {
assert(hasExtInfo());
return ExtInfo(Bits.AnyFunctionType.ExtInfoBits, getClangTypeInfo());
}

Expand All @@ -3002,6 +3015,7 @@ class AnyFunctionType : public TypeBase {
/// The parameter useClangFunctionType is present only for staging purposes.
/// In the future, we will always use the canonical clang function type.
ExtInfo getCanonicalExtInfo(bool useClangFunctionType) const {
assert(hasExtInfo());
return ExtInfo(Bits.AnyFunctionType.ExtInfoBits,
useClangFunctionType ? getCanonicalClangTypeInfo()
: ClangTypeInfo());
Expand Down Expand Up @@ -3193,7 +3207,7 @@ BEGIN_CAN_TYPE_WRAPPER(AnyFunctionType, Type)
static CanAnyFunctionType get(CanGenericSignature signature,
CanParamArrayRef params,
CanType result,
ExtInfo info = ExtInfo());
Optional<ExtInfo> info = None);

CanGenericSignature getOptGenericSignature() const;

Expand Down Expand Up @@ -3234,7 +3248,7 @@ class FunctionType final
public:
/// 'Constructor' Factory Function
static FunctionType *get(ArrayRef<Param> params, Type result,
ExtInfo info = ExtInfo());
Optional<ExtInfo> info = None);

// Retrieve the input parameters of this function type.
ArrayRef<Param> getParams() const {
Expand All @@ -3251,25 +3265,28 @@ class FunctionType final
}

void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getParams(), getResult(), getExtInfo());
Optional<ExtInfo> info = None;
if (hasExtInfo())
info = getExtInfo();
Profile(ID, getParams(), getResult(), info);
}
static void Profile(llvm::FoldingSetNodeID &ID,
ArrayRef<Param> params,
Type result,
ExtInfo info);
Optional<ExtInfo> info);

// Implement isa/cast/dyncast/etc.
static bool classof(const TypeBase *T) {
return T->getKind() == TypeKind::Function;
}

private:
FunctionType(ArrayRef<Param> params, Type result, ExtInfo info,
FunctionType(ArrayRef<Param> params, Type result, Optional<ExtInfo> info,
const ASTContext *ctx, RecursiveTypeProperties properties);
};
BEGIN_CAN_TYPE_WRAPPER(FunctionType, AnyFunctionType)
static CanFunctionType get(CanParamArrayRef params, CanType result,
ExtInfo info = ExtInfo()) {
Optional<ExtInfo> info = None) {
auto fnType = FunctionType::get(params.getOriginalArray(), result, info);
return cast<FunctionType>(fnType->getCanonicalType());
}
Expand Down Expand Up @@ -3334,7 +3351,7 @@ class GenericFunctionType final : public AnyFunctionType,
GenericFunctionType(GenericSignature sig,
ArrayRef<Param> params,
Type result,
ExtInfo info,
Optional<ExtInfo> info,
const ASTContext *ctx,
RecursiveTypeProperties properties);

Expand All @@ -3343,7 +3360,7 @@ class GenericFunctionType final : public AnyFunctionType,
static GenericFunctionType *get(GenericSignature sig,
ArrayRef<Param> params,
Type result,
ExtInfo info = ExtInfo());
Optional<ExtInfo> info = None);

// Retrieve the input parameters of this function type.
ArrayRef<Param> getParams() const {
Expand All @@ -3367,14 +3384,16 @@ class GenericFunctionType final : public AnyFunctionType,
FunctionType *substGenericArgs(llvm::function_ref<Type(Type)> substFn) const;

void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getGenericSignature(), getParams(), getResult(),
getExtInfo());
Optional<ExtInfo> info = None;
if (hasExtInfo())
info = getExtInfo();
Profile(ID, getGenericSignature(), getParams(), getResult(), info);
}
static void Profile(llvm::FoldingSetNodeID &ID,
GenericSignature sig,
ArrayRef<Param> params,
Type result,
ExtInfo info);
Optional<ExtInfo> info);

// Implement isa/cast/dyncast/etc.
static bool classof(const TypeBase *T) {
Expand All @@ -3387,11 +3406,11 @@ BEGIN_CAN_TYPE_WRAPPER(GenericFunctionType, AnyFunctionType)
static CanGenericFunctionType get(CanGenericSignature sig,
CanParamArrayRef params,
CanType result,
ExtInfo info = ExtInfo()) {
Optional<ExtInfo> info = None) {
// Knowing that the argument types are independently canonical is
// not sufficient to guarantee that the function type will be canonical.
auto fnType = GenericFunctionType::get(sig, params.getOriginalArray(),
result, info);
auto fnType =
GenericFunctionType::get(sig, params.getOriginalArray(), result, info);
return cast<GenericFunctionType>(fnType->getCanonicalType());
}

Expand All @@ -3413,7 +3432,7 @@ END_CAN_TYPE_WRAPPER(GenericFunctionType, AnyFunctionType)

inline CanAnyFunctionType
CanAnyFunctionType::get(CanGenericSignature signature, CanParamArrayRef params,
CanType result, ExtInfo extInfo) {
CanType result, Optional<ExtInfo> extInfo) {
if (signature) {
return CanGenericFunctionType::get(signature, params, result, extInfo);
} else {
Expand Down
58 changes: 33 additions & 25 deletions lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3245,18 +3245,19 @@ static void profileParams(llvm::FoldingSetNodeID &ID,
}

void FunctionType::Profile(llvm::FoldingSetNodeID &ID,
ArrayRef<AnyFunctionType::Param> params,
Type result,
ExtInfo info) {
ArrayRef<AnyFunctionType::Param> params, Type result,
Optional<ExtInfo> info) {
profileParams(ID, params);
ID.AddPointer(result.getPointer());
auto infoKey = info.getFuncAttrKey();
ID.AddInteger(infoKey.first);
ID.AddPointer(infoKey.second);
if (info.hasValue()) {
auto infoKey = info.getValue().getFuncAttrKey();
ID.AddInteger(infoKey.first);
ID.AddPointer(infoKey.second);
}
}

FunctionType *FunctionType::get(ArrayRef<AnyFunctionType::Param> params,
Type result, ExtInfo info) {
Type result, Optional<ExtInfo> info) {
auto properties = getFunctionRecursiveProperties(params, result);
auto arena = getArena(properties);

Expand All @@ -3272,10 +3273,15 @@ FunctionType *FunctionType::get(ArrayRef<AnyFunctionType::Param> params,
return funcTy;
}

auto clangTypeInfo = info.getClangTypeInfo();
ClangTypeInfo clangTypeInfo;
if (info.hasValue())
clangTypeInfo = info.getValue().getClangTypeInfo();

bool hasClangInfo =
info.hasValue() && !info.getValue().getClangTypeInfo().empty();

size_t allocSize = totalSizeToAlloc<AnyFunctionType::Param, ClangTypeInfo>(
params.size(), clangTypeInfo.empty() ? 0 : 1);
params.size(), hasClangInfo ? 1 : 0);
void *mem = ctx.Allocate(allocSize, alignof(FunctionType), arena);

bool isCanonical = isFunctionTypeCanonical(params, result);
Expand All @@ -3294,36 +3300,38 @@ FunctionType *FunctionType::get(ArrayRef<AnyFunctionType::Param> params,
}

// If the input and result types are canonical, then so is the result.
FunctionType::FunctionType(ArrayRef<AnyFunctionType::Param> params,
Type output, ExtInfo info,
const ASTContext *ctx,
FunctionType::FunctionType(ArrayRef<AnyFunctionType::Param> params, Type output,
Optional<ExtInfo> info, const ASTContext *ctx,
RecursiveTypeProperties properties)
: AnyFunctionType(TypeKind::Function, ctx,
output, properties, params.size(), info) {
: AnyFunctionType(TypeKind::Function, ctx, output, properties,
params.size(), info) {
std::uninitialized_copy(params.begin(), params.end(),
getTrailingObjects<AnyFunctionType::Param>());
auto clangTypeInfo = info.getClangTypeInfo();
if (!clangTypeInfo.empty())
*getTrailingObjects<ClangTypeInfo>() = clangTypeInfo;
if (info.hasValue()) {
auto clangTypeInfo = info.getValue().getClangTypeInfo();
if (!clangTypeInfo.empty())
*getTrailingObjects<ClangTypeInfo>() = clangTypeInfo;
}
}

void GenericFunctionType::Profile(llvm::FoldingSetNodeID &ID,
GenericSignature sig,
ArrayRef<AnyFunctionType::Param> params,
Type result,
ExtInfo info) {
Type result, Optional<ExtInfo> info) {
ID.AddPointer(sig.getPointer());
profileParams(ID, params);
ID.AddPointer(result.getPointer());
auto infoKey = info.getFuncAttrKey();
ID.AddInteger(infoKey.first);
ID.AddPointer(infoKey.second);
if (info.hasValue()) {
auto infoKey = info.getValue().getFuncAttrKey();
ID.AddInteger(infoKey.first);
ID.AddPointer(infoKey.second);
}
}

GenericFunctionType *GenericFunctionType::get(GenericSignature sig,
ArrayRef<Param> params,
Type result,
ExtInfo info) {
Optional<ExtInfo> info) {
assert(sig && "no generic signature for generic function type?!");
assert(!result->hasTypeVariable());
assert(!result->hasPlaceholder());
Expand All @@ -3346,7 +3354,7 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature sig,
// point.
bool isCanonical = isGenericFunctionTypeCanonical(sig, params, result);

assert(info.getClangTypeInfo().empty() &&
assert((!info.hasValue() || info.getValue().getClangTypeInfo().empty()) &&
"Generic functions do not have Clang types at the moment.");

if (auto funcTy
Expand All @@ -3370,7 +3378,7 @@ GenericFunctionType::GenericFunctionType(
GenericSignature sig,
ArrayRef<AnyFunctionType::Param> params,
Type result,
ExtInfo info,
Optional<ExtInfo> info,
const ASTContext *ctx,
RecursiveTypeProperties properties)
: AnyFunctionType(TypeKind::GenericFunction, ctx, result,
Expand Down
7 changes: 5 additions & 2 deletions lib/AST/ASTMangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2846,9 +2846,12 @@ CanType ASTMangler::getDeclTypeForMangling(

auto &C = decl->getASTContext();
if (decl->isInvalid()) {
if (isa<AbstractFunctionDecl>(decl))
if (isa<AbstractFunctionDecl>(decl)) {
// FIXME: Verify ExtInfo state is correct, not working by accident.
CanFunctionType::ExtInfo info;
return CanFunctionType::get({AnyFunctionType::Param(C.TheErrorType)},
C.TheErrorType);
C.TheErrorType, info);
}
return C.TheErrorType;
}

Expand Down
32 changes: 20 additions & 12 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4474,6 +4474,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
}

void printFunctionExtInfo(AnyFunctionType *fnType) {
if (!fnType->hasExtInfo()) {
Printer << "@_NO_EXTINFO ";
return;
}
auto &ctx = fnType->getASTContext();
auto info = fnType->getExtInfo();
if (Options.SkipAttributes)
Expand Down Expand Up @@ -4693,13 +4697,15 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
// If we're stripping argument labels from types, do it when printing.
visitAnyFunctionTypeParams(T->getParams(), /*printLabels*/false);

if (T->isAsync()) {
Printer << " ";
Printer.printKeyword("async", Options);
}
if (T->hasExtInfo()) {
if (T->isAsync()) {
Printer << " ";
Printer.printKeyword("async", Options);
}

if (T->isThrowing())
Printer << " " << tok::kw_throws;
if (T->isThrowing())
Printer << " " << tok::kw_throws;
}

Printer << " -> ";

Expand Down Expand Up @@ -4738,13 +4744,15 @@ class TypePrinter : public TypeVisitor<TypePrinter> {

visitAnyFunctionTypeParams(T->getParams(), /*printLabels*/true);

if (T->isAsync()) {
Printer << " ";
Printer.printKeyword("async", Options);
}
if (T->hasExtInfo()) {
if (T->isAsync()) {
Printer << " ";
Printer.printKeyword("async", Options);
}

if (T->isThrowing())
Printer << " " << tok::kw_throws;
if (T->isThrowing())
Printer << " " << tok::kw_throws;
}

Printer << " -> ";
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
Expand Down
Loading