Skip to content

Commit 8df8315

Browse files
Merge pull request #33541 from varungandhi-apple/vg-clang-types-in-sil-setup
Setup code for Clang types in SIL.
2 parents 592d427 + c4ad840 commit 8df8315

15 files changed

+167
-97
lines changed

include/swift/AST/ASTContext.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ namespace swift {
6262
class BoundGenericType;
6363
class ClangModuleLoader;
6464
class ClangNode;
65+
class ClangTypeConverter;
6566
class ConcreteDeclRef;
6667
class ConstructorDecl;
6768
class Decl;
@@ -586,6 +587,10 @@ class ASTContext final {
586587
Type getBridgedToObjC(const DeclContext *dc, Type type,
587588
Type *bridgedValueType = nullptr) const;
588589

590+
private:
591+
ClangTypeConverter &getClangTypeConverter();
592+
593+
public:
589594
/// Get the Clang type corresponding to a Swift function type.
590595
///
591596
/// \param params The function parameters.
@@ -595,6 +600,14 @@ class ASTContext final {
595600
getClangFunctionType(ArrayRef<AnyFunctionType::Param> params, Type resultTy,
596601
FunctionTypeRepresentation trueRep);
597602

603+
/// Get the canonical Clang type corresponding to a SIL function type.
604+
///
605+
/// SIL analog of \c ASTContext::getClangFunctionType .
606+
const clang::Type *
607+
getCanonicalClangFunctionType(
608+
ArrayRef<SILParameterInfo> params, Optional<SILResultInfo> result,
609+
SILFunctionType::Representation trueRep);
610+
598611
/// Get the Swift declaration that a Clang declaration was exported from,
599612
/// if applicable.
600613
const Decl *getSwiftDeclForExportedClangDecl(const clang::Decl *decl);

include/swift/AST/ExtInfo.h

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,8 @@ class ASTExtInfoBuilder {
194194

195195
using Representation = FunctionTypeRepresentation;
196196

197-
static void assertIsFunctionType(const clang::Type *);
198-
199197
ASTExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo)
200-
: bits(bits), clangTypeInfo(clangTypeInfo) {
201-
// TODO: [clang-function-type-serialization] Once we start serializing
202-
// the Clang type, we should also assert that the pointer is non-null.
203-
auto Rep = Representation(bits & RepresentationMask);
204-
if ((Rep == Representation::CFunctionPointer) && clangTypeInfo.type)
205-
assertIsFunctionType(clangTypeInfo.type);
206-
}
198+
: bits(bits), clangTypeInfo(clangTypeInfo) {}
207199

208200
public:
209201
// Constructor with all defaults.
@@ -254,10 +246,7 @@ class ASTExtInfoBuilder {
254246
DifferentiabilityKind::NonDifferentiable;
255247
}
256248

257-
/// Get the underlying ClangTypeInfo value if it is not the default value.
258-
Optional<ClangTypeInfo> getClangTypeInfo() const {
259-
return clangTypeInfo.empty() ? Optional<ClangTypeInfo>() : clangTypeInfo;
260-
}
249+
ClangTypeInfo getClangTypeInfo() const { return clangTypeInfo; }
261250

262251
constexpr SILFunctionTypeRepresentation getSILRepresentation() const {
263252
unsigned rawRep = bits & RepresentationMask;
@@ -404,9 +393,7 @@ class ASTExtInfo {
404393

405394
constexpr bool isDifferentiable() const { return builder.isDifferentiable(); }
406395

407-
Optional<ClangTypeInfo> getClangTypeInfo() const {
408-
return builder.getClangTypeInfo();
409-
}
396+
ClangTypeInfo getClangTypeInfo() const { return builder.getClangTypeInfo(); }
410397

411398
constexpr bool hasSelfParam() const { return builder.hasSelfParam(); }
412399

@@ -518,20 +505,32 @@ class SILExtInfoBuilder {
518505
SILExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo)
519506
: bits(bits), clangTypeInfo(clangTypeInfo) {}
520507

508+
static constexpr unsigned makeBits(Representation rep, bool isPseudogeneric,
509+
bool isNoEscape, bool isAsync,
510+
DifferentiabilityKind diffKind) {
511+
return ((unsigned)rep) | (isPseudogeneric ? PseudogenericMask : 0) |
512+
(isNoEscape ? NoEscapeMask : 0) | (isAsync ? AsyncMask : 0) |
513+
(((unsigned)diffKind << DifferentiabilityMaskOffset) &
514+
DifferentiabilityMask);
515+
}
516+
521517
public:
522518
// Constructor with all defaults.
523-
SILExtInfoBuilder() : bits(0), clangTypeInfo(ClangTypeInfo(nullptr)) {}
519+
SILExtInfoBuilder() : SILExtInfoBuilder(0, ClangTypeInfo(nullptr)) {}
524520

525521
// Constructor for polymorphic type.
526522
SILExtInfoBuilder(Representation rep, bool isPseudogeneric, bool isNoEscape,
527523
bool isAsync, DifferentiabilityKind diffKind,
528524
const clang::Type *type)
529-
: SILExtInfoBuilder(
530-
((unsigned)rep) | (isPseudogeneric ? PseudogenericMask : 0) |
531-
(isNoEscape ? NoEscapeMask : 0) | (isAsync ? AsyncMask : 0) |
532-
(((unsigned)diffKind << DifferentiabilityMaskOffset) &
533-
DifferentiabilityMask),
534-
ClangTypeInfo(type)) {}
525+
: SILExtInfoBuilder(makeBits(rep, isPseudogeneric, isNoEscape, isAsync,
526+
diffKind),
527+
ClangTypeInfo(type)) {}
528+
529+
SILExtInfoBuilder(ASTExtInfoBuilder info, bool isPseudogeneric)
530+
: SILExtInfoBuilder(makeBits(info.getSILRepresentation(), isPseudogeneric,
531+
info.isNoEscape(), info.isAsync(),
532+
info.getDifferentiabilityKind()),
533+
info.getClangTypeInfo()) {}
535534

536535
void checkInvariants() const;
537536

@@ -566,10 +565,8 @@ class SILExtInfoBuilder {
566565
DifferentiabilityKind::NonDifferentiable;
567566
}
568567

569-
/// Get the underlying ClangTypeInfo value if it is not the default value.
570-
Optional<ClangTypeInfo> getClangTypeInfo() const {
571-
return clangTypeInfo.empty() ? Optional<ClangTypeInfo>() : clangTypeInfo;
572-
}
568+
/// Get the underlying ClangTypeInfo value.
569+
ClangTypeInfo getClangTypeInfo() const { return clangTypeInfo; }
573570

574571
constexpr bool hasSelfParam() const {
575572
switch (getRepresentation()) {
@@ -697,9 +694,7 @@ class SILExtInfo {
697694

698695
constexpr bool isDifferentiable() const { return builder.isDifferentiable(); }
699696

700-
Optional<ClangTypeInfo> getClangTypeInfo() const {
701-
return builder.getClangTypeInfo();
702-
}
697+
ClangTypeInfo getClangTypeInfo() const { return builder.getClangTypeInfo(); }
703698

704699
constexpr bool hasSelfParam() const { return builder.hasSelfParam(); }
705700

include/swift/AST/Types.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2877,7 +2877,7 @@ class AnyFunctionType : public TypeBase {
28772877
unsigned NumParams, ExtInfo Info)
28782878
: TypeBase(Kind, CanTypeContext, properties), Output(Output) {
28792879
Bits.AnyFunctionType.ExtInfoBits = Info.getBits();
2880-
Bits.AnyFunctionType.HasClangTypeInfo = Info.getClangTypeInfo().hasValue();
2880+
Bits.AnyFunctionType.HasClangTypeInfo = !Info.getClangTypeInfo().empty();
28812881
Bits.AnyFunctionType.NumParams = NumParams;
28822882
assert(Bits.AnyFunctionType.NumParams == NumParams && "Params dropped!");
28832883
// The use of both assert() and static_assert() is intentional.

include/swift/SIL/TypeLowering.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -992,7 +992,6 @@ class TypeConverter {
992992
/// Given a function type, yield its bridged formal type.
993993
CanAnyFunctionType getBridgedFunctionType(AbstractionPattern fnPattern,
994994
CanAnyFunctionType fnType,
995-
AnyFunctionType::ExtInfo extInfo,
996995
Bridgeability bridging);
997996

998997
/// Given a referenced value and the substituted formal type of a

lib/AST/ASTContext.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3144,16 +3144,16 @@ FunctionType *FunctionType::get(ArrayRef<AnyFunctionType::Param> params,
31443144
return funcTy;
31453145
}
31463146

3147-
Optional<ClangTypeInfo> clangTypeInfo = info.getClangTypeInfo();
3147+
auto clangTypeInfo = info.getClangTypeInfo();
31483148

31493149
size_t allocSize = totalSizeToAlloc<AnyFunctionType::Param, ClangTypeInfo>(
3150-
params.size(), clangTypeInfo.hasValue() ? 1 : 0);
3150+
params.size(), clangTypeInfo.empty() ? 0 : 1);
31513151
void *mem = ctx.Allocate(allocSize, alignof(FunctionType), arena);
31523152

31533153
bool isCanonical = isFunctionTypeCanonical(params, result);
3154-
if (clangTypeInfo.hasValue()) {
3154+
if (!clangTypeInfo.empty()) {
31553155
if (ctx.LangOpts.UseClangFunctionTypes)
3156-
isCanonical &= clangTypeInfo->type->isCanonicalUnqualified();
3156+
isCanonical &= clangTypeInfo.getType()->isCanonicalUnqualified();
31573157
else
31583158
isCanonical = false;
31593159
}
@@ -3175,8 +3175,8 @@ FunctionType::FunctionType(ArrayRef<AnyFunctionType::Param> params,
31753175
std::uninitialized_copy(params.begin(), params.end(),
31763176
getTrailingObjects<AnyFunctionType::Param>());
31773177
auto clangTypeInfo = info.getClangTypeInfo();
3178-
if (clangTypeInfo.hasValue())
3179-
*getTrailingObjects<ClangTypeInfo>() = clangTypeInfo.getValue();
3178+
if (!clangTypeInfo.empty())
3179+
*getTrailingObjects<ClangTypeInfo>() = clangTypeInfo;
31803180
}
31813181

31823182
void GenericFunctionType::Profile(llvm::FoldingSetNodeID &ID,
@@ -4471,16 +4471,29 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type,
44714471
return Type();
44724472
}
44734473

4474-
const clang::Type *
4475-
ASTContext::getClangFunctionType(ArrayRef<AnyFunctionType::Param> params,
4476-
Type resultTy,
4477-
FunctionTypeRepresentation trueRep) {
4474+
ClangTypeConverter &ASTContext::getClangTypeConverter() {
44784475
auto &impl = getImpl();
44794476
if (!impl.Converter) {
44804477
auto *cml = getClangModuleLoader();
44814478
impl.Converter.emplace(*this, cml->getClangASTContext(), LangOpts.Target);
44824479
}
4483-
return impl.Converter.getValue().getFunctionType(params, resultTy, trueRep);
4480+
return impl.Converter.getValue();
4481+
}
4482+
4483+
const clang::Type *
4484+
ASTContext::getClangFunctionType(ArrayRef<AnyFunctionType::Param> params,
4485+
Type resultTy,
4486+
FunctionTypeRepresentation trueRep) {
4487+
return getClangTypeConverter().getFunctionType(params, resultTy, trueRep);
4488+
}
4489+
4490+
const clang::Type *
4491+
ASTContext::getCanonicalClangFunctionType(
4492+
ArrayRef<SILParameterInfo> params,
4493+
Optional<SILResultInfo> result,
4494+
SILFunctionType::Representation trueRep) {
4495+
auto *ty = getClangTypeConverter().getFunctionType(params, result, trueRep);
4496+
return ty ? ty->getCanonicalTypeInternal().getTypePtr() : nullptr;
44844497
}
44854498

44864499
const Decl *

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3629,7 +3629,7 @@ void printCType(ASTContext &Ctx, ASTPrinter &Printer, ExtInfo &info) {
36293629
auto *cml = Ctx.getClangModuleLoader();
36303630
SmallString<64> buf;
36313631
llvm::raw_svector_ostream os(buf);
3632-
info.getClangTypeInfo().getValue().printType(cml, os);
3632+
info.getClangTypeInfo().printType(cml, os);
36333633
Printer << ", cType: " << QuotedString(os.str());
36343634
}
36353635

@@ -4065,7 +4065,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
40654065
case SILFunctionType::Representation::CFunctionPointer:
40664066
Printer << "c";
40674067
// [TODO: Clang-type-plumbing] Remove the second check.
4068-
if (printNameOnly || !info.getClangTypeInfo().hasValue())
4068+
if (printNameOnly || info.getClangTypeInfo().empty())
40694069
break;
40704070
printCType(Ctx, Printer, info);
40714071
break;
@@ -4131,7 +4131,7 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
41314131
case SILFunctionType::Representation::CFunctionPointer:
41324132
Printer << "c";
41334133
// [TODO: Clang-type-plumbing] Remove the second check.
4134-
if (printNameOnly || !info.getClangTypeInfo().hasValue())
4134+
if (printNameOnly || info.getClangTypeInfo().empty())
41354135
break;
41364136
printCType(Ctx, Printer, info);
41374137
break;

lib/AST/ClangTypeConverter.cpp

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,57 @@ const clang::Type *ClangTypeConverter::getFunctionType(
158158
llvm_unreachable("invalid representation");
159159
}
160160

161+
const clang::Type *ClangTypeConverter::getFunctionType(
162+
ArrayRef<SILParameterInfo> params, Optional<SILResultInfo> result,
163+
SILFunctionType::Representation repr) {
164+
165+
// Using the interface type is sufficient as type parameters get mapped to
166+
// `id`, since ObjC lightweight generics use type erasure. (See also: SE-0057)
167+
auto resultClangTy = result.hasValue()
168+
? convert(result.getValue().getInterfaceType())
169+
: ClangASTContext.VoidTy;
170+
171+
if (resultClangTy.isNull())
172+
return nullptr;
173+
174+
SmallVector<clang::FunctionProtoType::ExtParameterInfo, 4> extParamInfos;
175+
SmallVector<clang::QualType, 4> paramsClangTy;
176+
bool someParamIsConsumed = false;
177+
for (auto &p : params) {
178+
auto pc = convert(p.getInterfaceType());
179+
if (pc.isNull())
180+
return nullptr;
181+
clang::FunctionProtoType::ExtParameterInfo extParamInfo;
182+
if (p.isConsumed()) {
183+
someParamIsConsumed = true;
184+
extParamInfo = extParamInfo.withIsConsumed(true);
185+
}
186+
extParamInfos.push_back(extParamInfo);
187+
paramsClangTy.push_back(pc);
188+
}
189+
190+
clang::FunctionProtoType::ExtProtoInfo info(clang::CallingConv::CC_C);
191+
if (someParamIsConsumed)
192+
info.ExtParameterInfos = extParamInfos.begin();
193+
auto fn = ClangASTContext.getFunctionType(resultClangTy, paramsClangTy, info);
194+
if (fn.isNull())
195+
return nullptr;
196+
197+
switch (repr) {
198+
case SILFunctionType::Representation::CFunctionPointer:
199+
return ClangASTContext.getPointerType(fn).getTypePtr();
200+
case SILFunctionType::Representation::Block:
201+
return ClangASTContext.getBlockPointerType(fn).getTypePtr();
202+
case SILFunctionType::Representation::Thick:
203+
case SILFunctionType::Representation::Thin:
204+
case SILFunctionType::Representation::Method:
205+
case SILFunctionType::Representation::ObjCMethod:
206+
case SILFunctionType::Representation::WitnessMethod:
207+
case SILFunctionType::Representation::Closure:
208+
llvm_unreachable("Expected a C-compatible representation.");
209+
}
210+
}
211+
161212
clang::QualType ClangTypeConverter::convertMemberType(NominalTypeDecl *DC,
162213
StringRef memberName) {
163214
auto memberTypeDecl = cast<TypeDecl>(
@@ -576,12 +627,19 @@ clang::QualType ClangTypeConverter::visitFunctionType(FunctionType *type) {
576627
}
577628

578629
clang::QualType ClangTypeConverter::visitSILFunctionType(SILFunctionType *type) {
579-
llvm::report_fatal_error("Expected only AST types but found a SIL function.");
630+
// We must've already computed it before if applicable.
631+
return clang::QualType(type->getClangTypeInfo().getType(), 0);
580632
}
581633

582634
clang::QualType
583635
ClangTypeConverter::visitSILBlockStorageType(SILBlockStorageType *type) {
584-
llvm::report_fatal_error("Expected only AST types but found a SIL block.");
636+
// We'll select (void)(^)(). This isn't correct for all blocks, but block
637+
// storage type should only be converted for function signature lowering,
638+
// where the parameter types do not matter.
639+
auto &clangCtx = ClangASTContext;
640+
auto fnTy = clangCtx.getFunctionNoProtoType(clangCtx.VoidTy);
641+
auto blockTy = clangCtx.getBlockPointerType(fnTy);
642+
return clangCtx.getCanonicalType(blockTy);
585643
}
586644

587645
clang::QualType

lib/AST/ClangTypeConverter.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ class ClangTypeConverter :
7474
ArrayRef<AnyFunctionType::Param> params, Type resultTy,
7575
AnyFunctionType::Representation repr);
7676

77+
/// Compute the C function type for a SIL function type.
78+
const clang::Type *getFunctionType(
79+
ArrayRef<SILParameterInfo> params, Optional<SILResultInfo> result,
80+
SILFunctionType::Representation repr);
81+
7782
/// Check whether the given Clang declaration is an export of a Swift
7883
/// declaration introduced by this converter, and if so, return the original
7984
/// Swift declaration.

lib/AST/ExtInfo.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,20 @@
1919

2020
#include "clang/AST/Type.h"
2121

22+
static void assertIsFunctionType(const clang::Type *type) {
23+
#ifndef NDEBUG
24+
if (!(type->isFunctionPointerType() || type->isBlockPointerType() ||
25+
type->isFunctionReferenceType())) {
26+
llvm::SmallString<256> buf;
27+
llvm::raw_svector_ostream os(buf);
28+
os << "Expected a Clang function type wrapped in a pointer type or "
29+
<< "a block pointer type but found:\n";
30+
type->dump(os);
31+
llvm_unreachable(os.str().data());
32+
}
33+
#endif
34+
}
35+
2236
namespace swift {
2337

2438
// MARK: - ClangTypeInfo
@@ -53,23 +67,12 @@ void ClangTypeInfo::dump(llvm::raw_ostream &os) const {
5367

5468
// MARK: - ASTExtInfoBuilder
5569

56-
void ASTExtInfoBuilder::assertIsFunctionType(const clang::Type *type) {
57-
#ifndef NDEBUG
58-
if (!(type->isFunctionPointerType() || type->isBlockPointerType() ||
59-
type->isFunctionReferenceType())) {
60-
SmallString<256> buf;
61-
llvm::raw_svector_ostream os(buf);
62-
os << "Expected a Clang function type wrapped in a pointer type or "
63-
<< "a block pointer type but found:\n";
64-
type->dump(os);
65-
llvm_unreachable(os.str().data());
66-
}
67-
#endif
68-
return;
69-
}
70-
7170
void ASTExtInfoBuilder::checkInvariants() const {
72-
// TODO: Add validation checks here while making sure things don't blow up.
71+
// TODO: [clang-function-type-serialization] Once we start serializing
72+
// the Clang type, we should also assert that the pointer is non-null.
73+
auto Rep = Representation(bits & RepresentationMask);
74+
if ((Rep == Representation::CFunctionPointer) && clangTypeInfo.type)
75+
assertIsFunctionType(clangTypeInfo.type);
7376
}
7477

7578
// MARK: - ASTExtInfo

0 commit comments

Comments
 (0)