From f07ba79377fe78878726a9fabbaf087faad8d0f9 Mon Sep 17 00:00:00 2001 From: Varun Gandhi Date: Wed, 15 Jan 2020 16:15:29 -0800 Subject: [PATCH 1/5] [NFC] Fix incorrect comment in ExtInfo's constructor. --- include/swift/AST/Types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 0ffd3a600eb17..98893c5907f79 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -2969,7 +2969,7 @@ class AnyFunctionType : public TypeBase { static void assertIsFunctionType(const clang::Type *); ExtInfo(unsigned Bits, Uncommon Other) : Bits(Bits), Other(Other) { - // TODO: [store-sil-clang-function-type] Once we start serializing + // TODO: [clang-function-type-serialization] Once we start serializing // the Clang type, we should also assert that the pointer is non-null. auto Rep = Representation(Bits & RepresentationMask); if ((Rep == Representation::CFunctionPointer) && Other.ClangFunctionType) From feb76eaf18a40eb566c78a3ac52c254229d9267a Mon Sep 17 00:00:00 2001 From: Varun Gandhi Date: Wed, 15 Jan 2020 16:15:34 -0800 Subject: [PATCH 2/5] [AST] Support SILFunctionType/SILBlockStorageType in ClangTypeConverter. This is needed before we can store Clang types in SILFunctionType. --- lib/AST/ClangTypeConverter.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp index 56b07d0dcd17b..e82198bf2a094 100644 --- a/lib/AST/ClangTypeConverter.cpp +++ b/lib/AST/ClangTypeConverter.cpp @@ -570,12 +570,19 @@ clang::QualType ClangTypeConverter::visitFunctionType(FunctionType *type) { } clang::QualType ClangTypeConverter::visitSILFunctionType(SILFunctionType *type) { - llvm::report_fatal_error("Expected only AST types but found a SIL function."); + // We must've already computed it before if applicable. + return clang::QualType(type->getClangFunctionType(), 0); } clang::QualType ClangTypeConverter::visitSILBlockStorageType(SILBlockStorageType *type) { - llvm::report_fatal_error("Expected only AST types but found a SIL block."); + // We'll select (void)(^)(). This isn't correct for all blocks, but block + // storage type should only be converted for function signature lowering, + // where the parameter types do not matter. + auto &clangCtx = ClangASTContext; + auto fnTy = clangCtx.getFunctionNoProtoType(clangCtx.VoidTy); + auto blockTy = clangCtx.getBlockPointerType(fnTy); + return clangCtx.getCanonicalType(blockTy); } clang::QualType From bfa2f98d954575fd0c6f66536f0fded697fa6d1c Mon Sep 17 00:00:00 2001 From: Varun Gandhi Date: Wed, 15 Jan 2020 16:15:37 -0800 Subject: [PATCH 3/5] [AST] Add functionality for computing Clang types for SIL functions. --- include/swift/AST/ASTContext.h | 13 +++++++++ lib/AST/ASTContext.cpp | 30 ++++++++++++++++---- lib/AST/ClangTypeConverter.cpp | 51 ++++++++++++++++++++++++++++++++++ lib/AST/ClangTypeConverter.h | 4 +++ 4 files changed, 92 insertions(+), 6 deletions(-) diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index 0e5e0fca8ad41..28115f46800fa 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -576,6 +576,10 @@ class ASTContext final { Type getBridgedToObjC(const DeclContext *dc, Type type, Type *bridgedValueType = nullptr) const; +private: + void initializeClangTypeConverter(); + +public: /// Get the Clang type corresponding to a Swift function type. /// /// \param params The function parameters. @@ -589,6 +593,15 @@ class ASTContext final { const FunctionType::ExtInfo incompleteExtInfo, FunctionTypeRepresentation trueRep); + /// Get the canonical Clang type corresponding to a SIL function type. + /// + /// SIL analog of \c ASTContext::getClangFunctionType . + const clang::Type * + getCanonicalClangFunctionType( + ArrayRef params, Optional result, + const SILFunctionType::ExtInfo incompleteExtInfo, + SILFunctionType::Representation trueRep); + /// Determine whether the given Swift type is representable in a /// given foreign language. ForeignRepresentationInfo diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index b335fa071117b..2811987bd5c3e 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4372,17 +4372,35 @@ Type ASTContext::getBridgedToObjC(const DeclContext *dc, Type type, return Type(); } -const clang::Type * -ASTContext::getClangFunctionType(ArrayRef params, - Type resultTy, - FunctionType::ExtInfo incompleteExtInfo, - FunctionTypeRepresentation trueRep) { +void +ASTContext::initializeClangTypeConverter() { auto &impl = getImpl(); if (!impl.Converter) { auto *cml = getClangModuleLoader(); impl.Converter.emplace(*this, cml->getClangASTContext(), LangOpts.Target); } - return impl.Converter.getValue().getFunctionType(params, resultTy, trueRep); +} + +const clang::Type * +ASTContext::getClangFunctionType(ArrayRef params, + Type resultTy, + FunctionType::ExtInfo incompleteExtInfo, + FunctionTypeRepresentation trueRep) { + initializeClangTypeConverter(); + return getImpl().Converter.getValue().getFunctionType(params, resultTy, + trueRep); +} + +const clang::Type * +ASTContext::getCanonicalClangFunctionType( + ArrayRef params, + Optional result, + SILFunctionType::ExtInfo incompleteExtInfo, + SILFunctionType::Representation trueRep) { + initializeClangTypeConverter(); + auto *ty = getImpl().Converter.getValue().getFunctionType(params, result, + trueRep); + return ty ? ty->getCanonicalTypeInternal().getTypePtr() : nullptr; } CanGenericSignature ASTContext::getSingleGenericParameterSignature() const { diff --git a/lib/AST/ClangTypeConverter.cpp b/lib/AST/ClangTypeConverter.cpp index e82198bf2a094..8ebc7816ebcae 100644 --- a/lib/AST/ClangTypeConverter.cpp +++ b/lib/AST/ClangTypeConverter.cpp @@ -156,6 +156,57 @@ const clang::Type *ClangTypeConverter::getFunctionType( } } +const clang::Type *ClangTypeConverter::getFunctionType( + ArrayRef params, Optional result, + SILFunctionType::Representation repr) { + + // Using the interface type is sufficient as Swift does not allow abstracting + // over @convention(c) functions, hence we don't need any substitutions. + auto resultClangTy = result.hasValue() + ? convert(result.getValue().getInterfaceType()) + : ClangASTContext.VoidTy; + + if (resultClangTy.isNull()) + return nullptr; + + SmallVector extParamInfos; + SmallVector paramsClangTy; + bool someParamIsConsumed = false; + for (auto &p : params) { + auto pc = convert(p.getInterfaceType()); + if (pc.isNull()) + return nullptr; + clang::FunctionProtoType::ExtParameterInfo extParamInfo; + if (p.isConsumed()) { + someParamIsConsumed = true; + extParamInfo = extParamInfo.withIsConsumed(true); + } + extParamInfos.push_back(extParamInfo); + paramsClangTy.push_back(pc); + } + + clang::FunctionProtoType::ExtProtoInfo info(clang::CallingConv::CC_C); + if (someParamIsConsumed) + info.ExtParameterInfos = extParamInfos.begin(); + auto fn = ClangASTContext.getFunctionType(resultClangTy, paramsClangTy, info); + if (fn.isNull()) + return nullptr; + + switch (repr) { + case SILFunctionType::Representation::CFunctionPointer: + return ClangASTContext.getPointerType(fn).getTypePtr(); + case SILFunctionType::Representation::Block: + return ClangASTContext.getBlockPointerType(fn).getTypePtr(); + case SILFunctionType::Representation::Thick: + case SILFunctionType::Representation::Thin: + case SILFunctionType::Representation::Method: + case SILFunctionType::Representation::ObjCMethod: + case SILFunctionType::Representation::WitnessMethod: + case SILFunctionType::Representation::Closure: + llvm_unreachable("Expected a C-compatible representation."); + } +} + clang::QualType ClangTypeConverter::convertMemberType(NominalTypeDecl *DC, StringRef memberName) { auto memberTypeDecl = cast( diff --git a/lib/AST/ClangTypeConverter.h b/lib/AST/ClangTypeConverter.h index b25f6b6dffb92..69820ae47f7bc 100644 --- a/lib/AST/ClangTypeConverter.h +++ b/lib/AST/ClangTypeConverter.h @@ -73,6 +73,10 @@ class ClangTypeConverter : ArrayRef params, Type resultTy, AnyFunctionType::Representation repr); + const clang::Type *getFunctionType( + ArrayRef params, Optional result, + SILFunctionType::Representation repr); + private: clang::QualType convert(Type type); clang::QualType convertMemberType(NominalTypeDecl *DC, From 5f458207557dd32a70b75c6bc9db4651c06b504f Mon Sep 17 00:00:00 2001 From: Varun Gandhi Date: Wed, 15 Jan 2020 16:15:41 -0800 Subject: [PATCH 4/5] [AST] Store Clang type in SILFunctionType for @convention(c) functions. --- include/swift/AST/Types.h | 88 ++++++++++++++++++++++---------- lib/AST/ASTContext.cpp | 24 +++++++-- lib/AST/ASTDemangler.cpp | 26 +++++++--- lib/AST/Type.cpp | 20 ++++++-- lib/ClangImporter/ImportType.cpp | 9 ++-- lib/SIL/SILFunctionType.cpp | 5 +- lib/SILGen/SILGen.cpp | 16 +++--- lib/SILGen/SILGenBridging.cpp | 16 ++++-- lib/SILGen/SILGenFunction.cpp | 29 ++++++----- lib/Sema/TypeCheckType.cpp | 48 ++++++++++++----- 10 files changed, 192 insertions(+), 89 deletions(-) diff --git a/include/swift/AST/Types.h b/include/swift/AST/Types.h index 98893c5907f79..cacf039e53743 100644 --- a/include/swift/AST/Types.h +++ b/include/swift/AST/Types.h @@ -44,7 +44,6 @@ namespace clang { class Type; -class FunctionType; } // namespace clang namespace llvm { @@ -2947,6 +2946,7 @@ class AnyFunctionType : public TypeBase { friend ExtInfo; friend class AnyFunctionType; friend class FunctionType; + friend class SILUncommonInfo; // We preserve a full clang::Type *, not a clang::FunctionType * as: // 1. We need to keep sugar in case we need to present an error to the user. // 2. The actual type being stored is [ignoring sugar] either a @@ -3917,6 +3917,24 @@ namespace Lowering { class TypeConverter; }; +class SILUncommonInfo { + friend class SILFunctionType; + + // Invariant: The FunctionType is canonical. + // We store a clang::FunctionType * instead of a clang::CanQualType to + // avoid depending on the Clang AST in this header. + const clang::Type *ClangFunctionType; + + bool empty() const { return !ClangFunctionType; } + SILUncommonInfo(const clang::Type *type) : ClangFunctionType(type) {} + SILUncommonInfo(AnyFunctionType::ExtInfo::Uncommon uncommon); + +public: + /// Analog of AnyFunctionType::ExtInfo::Uncommon::printClangFunctionType. + void printClangFunctionType(ClangModuleLoader *cml, + llvm::raw_ostream &os) const; +}; + /// SILFunctionType - The lowered type of a function value, suitable /// for use by SIL. /// @@ -3925,7 +3943,8 @@ namespace Lowering { /// function parameter and result types. class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, private llvm::TrailingObjects { + SILResultInfo, SILYieldInfo, CanType, + SILUncommonInfo> { friend TrailingObjects; size_t numTrailingObjects(OverloadToken) const { @@ -3944,6 +3963,10 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, return hasResultCache() ? 2 : 0; } + size_t numTrailingObjects(OverloadToken) const { + return Bits.SILFunctionType.HasUncommonInfo ? 1 : 0; + } + public: using Language = SILFunctionLanguage; using Representation = SILFunctionTypeRepresentation; @@ -3968,27 +3991,31 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, unsigned Bits; // Naturally sized for speed. - class Uncommon { - friend ExtInfo; - friend class SILFunctionType; - - // Invariant: The FunctionType is canonical. - // We store a clang::FunctionType * instead of a clang::CanQualType to - // avoid depending on the Clang AST in this header. - const clang::FunctionType *ClangFunctionType; + // For symmetry with AnyFunctionType::Uncommon + using Uncommon = SILUncommonInfo; - bool empty() const { return !ClangFunctionType; } - Uncommon(const clang::FunctionType *type) : ClangFunctionType(type) {} + Uncommon Other; - public: - /// Analog of AnyFunctionType::ExtInfo::Uncommon::printClangFunctionType. - void printClangFunctionType(ClangModuleLoader *cml, - llvm::raw_ostream &os) const; - }; + static void assertIsFunctionType(const clang::Type *); - Uncommon Other; + ExtInfo(unsigned Bits, Uncommon Other) : Bits(Bits), Other(Other) { + auto Rep = Representation(Bits & RepresentationMask); + // TODO: [clang-function-type-serialization] Once we start serializing + // the Clang type, we should also assert that the pointer is non-null. + if ((Rep == Representation::CFunctionPointer) && Other.ClangFunctionType) + assertIsFunctionType(Other.ClangFunctionType); + } - ExtInfo(unsigned Bits, Uncommon Other) : Bits(Bits), Other(Other) {} + static constexpr unsigned makeBits(Representation rep, + bool isPseudogeneric, + bool isNoEscape, + DifferentiabilityKind diffKind) { + return ((unsigned) rep) + | (isPseudogeneric ? PseudogenericMask : 0) + | (isNoEscape ? NoEscapeMask : 0) + | (((unsigned)diffKind << DifferentiabilityMaskOffset) + & DifferentiabilityMask); + } friend class SILFunctionType; public: @@ -3998,15 +4025,21 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, // Constructor for polymorphic type. ExtInfo(Representation rep, bool isPseudogeneric, bool isNoEscape, DifferentiabilityKind diffKind, - const clang::FunctionType *type) - : ExtInfo(((unsigned) rep) - | (isPseudogeneric ? PseudogenericMask : 0) - | (isNoEscape ? NoEscapeMask : 0) - | (((unsigned)diffKind << DifferentiabilityMaskOffset) - & DifferentiabilityMask), + const clang::Type *type) + : ExtInfo(makeBits(rep, isPseudogeneric, isNoEscape, diffKind), Uncommon(type)) { } + ExtInfo(AnyFunctionType::ExtInfo info, bool isPseudogeneric) + : ExtInfo(makeBits(info.getSILRepresentation(), + isPseudogeneric, + info.isNoEscape(), + info.getDifferentiabilityKind()), + info.getUncommonInfo().hasValue() + ? Uncommon(info.getUncommonInfo().getValue()) + : Uncommon(nullptr)) { + } + static ExtInfo getThin() { return ExtInfo(Representation::Thin, false, false, DifferentiabilityKind::NonDifferentiable, nullptr); @@ -4093,6 +4126,9 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, return ExtInfo(NoEscape ? (Bits | NoEscapeMask) : (Bits & ~NoEscapeMask), Other); } + ExtInfo withClangFunctionType(const clang::Type *type) const { + return ExtInfo(Bits, Uncommon(type)); + } std::pair getFuncAttrKey() const { return std::make_pair(Bits, Other.ClangFunctionType); @@ -4388,7 +4424,7 @@ class SILFunctionType final : public TypeBase, public llvm::FoldingSetNode, return WitnessMethodConformance; } - const clang::FunctionType *getClangFunctionType() const; + const clang::Type *getClangFunctionType() const; ExtInfo getExtInfo() const { return ExtInfo(Bits.SILFunctionType.ExtInfoBits, getClangFunctionType()); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 2811987bd5c3e..f7ad4fb5792da 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -3158,7 +3158,13 @@ ArrayRef GenericFunctionType::getRequirements() const { return Signature->getRequirements(); } -void SILFunctionType::ExtInfo::Uncommon::printClangFunctionType( +SILUncommonInfo::SILUncommonInfo(AnyFunctionType::ExtInfo::Uncommon uncommon) { + auto *ty = uncommon.ClangFunctionType; + ClangFunctionType = ty ? ty->getCanonicalTypeInternal().getTypePtr() + : nullptr; +} + +void SILUncommonInfo::printClangFunctionType( ClangModuleLoader *cml, llvm::raw_ostream &os) const { cml->printClangType(ClangFunctionType, os); } @@ -3224,11 +3230,11 @@ SILFunctionType::SILFunctionType( Bits.SILFunctionType.HasErrorResult = errorResult.hasValue(); Bits.SILFunctionType.ExtInfoBits = ext.Bits; - Bits.SILFunctionType.HasUncommonInfo = false; // The use of both assert() and static_assert() below is intentional. assert(Bits.SILFunctionType.ExtInfoBits == ext.Bits && "Bits were dropped!"); static_assert(ExtInfo::NumMaskBits == NumSILExtInfoBits, "ExtInfo and SILFunctionTypeBitfields must agree on bit size"); + Bits.SILFunctionType.HasUncommonInfo = ext.getUncommonInfo().hasValue(); Bits.SILFunctionType.CoroutineKind = unsigned(coroutineKind); NumParameters = params.size(); if (coroutineKind == SILCoroutineKind::None) { @@ -3261,6 +3267,9 @@ SILFunctionType::SILFunctionType( getMutableFormalResultsCache() = CanType(); getMutableAllResultsCache() = CanType(); } + if (auto uncommon = ext.getUncommonInfo()) + *getTrailingObjects() = uncommon.getValue(); + #ifndef NDEBUG if (ext.getRepresentation() == Representation::WitnessMethod) assert(!WitnessMethodConformance.isInvalid() && @@ -3360,6 +3369,10 @@ CanSILFunctionType SILFunctionType::get( assert(coroutineKind != SILCoroutineKind::None || yields.empty()); assert(!ext.isPseudogeneric() || genericSig); + // FIXME: [clang-function-type-serialization] Don't drop the Clang type... + if (!ctx.LangOpts.UseClangFunctionTypes) + ext = ext.withClangFunctionType(nullptr); + llvm::FoldingSetNodeID id; SILFunctionType::Profile(id, genericSig, ext, coroutineKind, callee, params, yields, normalResults, errorResult, @@ -3376,10 +3389,11 @@ CanSILFunctionType SILFunctionType::get( // See [SILFunctionType-layout] bool hasResultCache = normalResults.size() > 1; - size_t bytes = - totalSizeToAlloc( + size_t bytes = totalSizeToAlloc( params.size(), normalResults.size() + (errorResult ? 1 : 0), - yields.size(), hasResultCache ? 2 : 0); + yields.size(), hasResultCache ? 2 : 0, + ext.getUncommonInfo().hasValue() ? 1 : 0); void *mem = ctx.Allocate(bytes, alignof(SILFunctionType)); diff --git a/lib/AST/ASTDemangler.cpp b/lib/AST/ASTDemangler.cpp index 7be40882ef5b2..86fbd7b5e8af2 100644 --- a/lib/AST/ASTDemangler.cpp +++ b/lib/AST/ASTDemangler.cpp @@ -488,12 +488,6 @@ Type ASTBuilder::createImplFunctionType( break; } - // TODO: [store-sil-clang-function-type] - auto einfo = SILFunctionType::ExtInfo( - representation, flags.isPseudogeneric(), !flags.isEscaping(), - DifferentiabilityKind::NonDifferentiable, - /*clangFunctionType*/ nullptr); - llvm::SmallVector funcParams; llvm::SmallVector funcYields; llvm::SmallVector funcResults; @@ -516,6 +510,26 @@ Type ASTBuilder::createImplFunctionType( auto conv = getResultConvention(errorResult->getConvention()); funcErrorResult.emplace(type, conv); } + + const clang::Type *clangFnType = nullptr; + auto incompleteExtInfo = SILFunctionType::ExtInfo( + SILFunctionType::Representation::Thick, flags.isPseudogeneric(), + !flags.isEscaping(), DifferentiabilityKind::NonDifferentiable, + clangFnType); + + if (representation == SILFunctionType::Representation::CFunctionPointer) { + assert(funcResults.size() <= 1 && funcYields.size() == 0 + && "@convention(c) functions have at most 1 result and 0 yields."); + auto result = funcResults.empty() ? Optional() + : funcResults[0]; + auto &Context = getASTContext(); + clangFnType = Context.getCanonicalClangFunctionType(funcParams, result, + incompleteExtInfo, + representation); + } + auto einfo = incompleteExtInfo.withRepresentation(representation) + .withClangFunctionType(clangFnType); + return SILFunctionType::get(genericSig, einfo, funcCoroutineKind, funcCalleeConvention, funcParams, funcYields, funcResults, funcErrorResult, diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 679962777c587..577d8e025b7d8 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -3229,8 +3229,7 @@ void AnyFunctionType::ExtInfo::Uncommon::printClangFunctionType( cml->printClangType(ClangFunctionType, os); } -void -AnyFunctionType::ExtInfo::assertIsFunctionType(const clang::Type *type) { +static void assertIsFunctionType(const clang::Type *type) { #ifndef NDEBUG if (!(type->isFunctionPointerType() || type->isBlockPointerType())) { SmallString<256> buf; @@ -3244,6 +3243,10 @@ AnyFunctionType::ExtInfo::assertIsFunctionType(const clang::Type *type) { return; } +void AnyFunctionType::ExtInfo::assertIsFunctionType(const clang::Type *type) { + ::assertIsFunctionType(type); +} + const clang::Type *AnyFunctionType::getClangFunctionType() const { switch (getKind()) { case TypeKind::Function: @@ -3261,9 +3264,16 @@ const clang::Type *AnyFunctionType::getCanonicalClangFunctionType() const { return ty ? ty->getCanonicalTypeInternal().getTypePtr() : nullptr; } -// TODO: [store-sil-clang-function-type] -const clang::FunctionType *SILFunctionType::getClangFunctionType() const { - return nullptr; +void SILFunctionType::ExtInfo::assertIsFunctionType(const clang::Type *type) { + ::assertIsFunctionType(type); +} + +const clang::Type *SILFunctionType::getClangFunctionType() const { + if (!Bits.SILFunctionType.HasUncommonInfo) + return nullptr; + auto *type = getTrailingObjects()->ClangFunctionType; + assert(type && "If the pointer was null, we shouldn't have stored it."); + return type; } FunctionType * diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index 854a4f29d78fa..9db87d47b901d 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -416,12 +416,11 @@ namespace { if (pointeeQualType->isFunctionType()) { auto funcTy = pointeeType->castTo(); - return { - FunctionType::get(funcTy->getParams(), funcTy->getResult(), - funcTy->getExtInfo() - .withRepresentation( + auto extInfo = funcTy->getExtInfo().withRepresentation( AnyFunctionType::Representation::CFunctionPointer) - .withClangFunctionType(type)), + .withClangFunctionType(type); + return { + FunctionType::get(funcTy->getParams(), funcTy->getResult(), extInfo), ImportHint::CFunctionPointer }; } diff --git a/lib/SIL/SILFunctionType.cpp b/lib/SIL/SILFunctionType.cpp index df9384141bf26..efdc2663b0309 100644 --- a/lib/SIL/SILFunctionType.cpp +++ b/lib/SIL/SILFunctionType.cpp @@ -1266,10 +1266,7 @@ static CanSILFunctionType getSILFunctionType( // NOTE: SILFunctionType::ExtInfo doesn't track everything that // AnyFunctionType::ExtInfo tracks. For example: 'throws' or 'auto-closure' - auto silExtInfo = SILFunctionType::ExtInfo() - .withRepresentation(extInfo.getSILRepresentation()) - .withIsPseudogeneric(pseudogeneric) - .withNoEscape(extInfo.isNoEscape()); + SILFunctionType::ExtInfo silExtInfo(extInfo, pseudogeneric); // Build the substituted generic signature we extracted. bool impliedSignature = false; diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index 888aadc02cf78..d682dcbba732f 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -452,8 +452,6 @@ SILGenModule::getKeyPathProjectionCoroutine(bool isReadAccess, SILFunction *SILGenModule::emitTopLevelFunction(SILLocation Loc) { ASTContext &C = getASTContext(); - auto extInfo = SILFunctionType::ExtInfo() - .withRepresentation(SILFunctionType::Representation::CFunctionPointer); // Use standard library types if we have them; otherwise, fall back to // builtins. @@ -484,13 +482,19 @@ SILFunction *SILGenModule::emitTopLevelFunction(SILLocation Loc) { SILParameterInfo(PtrPtrInt8Ty, ParameterConvention::Direct_Unowned), }; + SILResultInfo results[] = {SILResultInfo(Int32Ty, ResultConvention::Unowned)}; + + auto rep = SILFunctionType::Representation::CFunctionPointer; + auto incompleteExtInfo = SILFunctionType::ExtInfo(); + auto *clangTy = C.getCanonicalClangFunctionType(params, results[0], + incompleteExtInfo, rep); + auto extInfo = incompleteExtInfo.withRepresentation(rep) + .withClangFunctionType(clangTy); + CanSILFunctionType topLevelType = SILFunctionType::get(nullptr, extInfo, SILCoroutineKind::None, ParameterConvention::Direct_Unowned, - params, /*yields*/ {}, - SILResultInfo(Int32Ty, - ResultConvention::Unowned), - None, + params, /*yields*/ {}, results, None, SubstitutionMap(), false, C); diff --git a/lib/SILGen/SILGenBridging.cpp b/lib/SILGen/SILGenBridging.cpp index 9ecb35559c539..ccadd0370dbdb 100644 --- a/lib/SILGen/SILGenBridging.cpp +++ b/lib/SILGen/SILGenBridging.cpp @@ -541,9 +541,16 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc, blockInterfaceTy->getParameters().end(), std::back_inserter(params)); - auto extInfo = - SILFunctionType::ExtInfo() - .withRepresentation(SILFunctionType::Representation::CFunctionPointer); + auto results = blockInterfaceTy->getResults(); + auto incompleteExtInfo = SILFunctionType::ExtInfo(); + auto *clangFnType = getASTContext().getCanonicalClangFunctionType( + params, results.empty() ? Optional() : results[0], + incompleteExtInfo, + SILFunctionType::Representation::CFunctionPointer); + + auto extInfo = incompleteExtInfo + .withRepresentation(SILFunctionType::Representation::CFunctionPointer) + .withClangFunctionType(clangFnType); CanGenericSignature genericSig; GenericEnvironment *genericEnv = nullptr; @@ -568,8 +575,7 @@ ManagedValue SILGenFunction::emitFuncToBlock(SILLocation loc, auto invokeTy = SILFunctionType::get( genericSig, extInfo, SILCoroutineKind::None, - ParameterConvention::Direct_Unowned, params, - /*yields*/ {}, blockInterfaceTy->getResults(), + ParameterConvention::Direct_Unowned, params, /*yields*/ {}, results, blockInterfaceTy->getOptionalErrorResult(), SubstitutionMap(), false, getASTContext()); diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index 96ba74a233131..be314c5fbe551 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -577,20 +577,21 @@ void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) { CanType anyObjectMetaTy = CanExistentialMetatypeType::get(anyObjectTy, MetatypeRepresentation::ObjC); - auto NSStringFromClassType = SILFunctionType::get(nullptr, - SILFunctionType::ExtInfo() - .withRepresentation(SILFunctionType::Representation:: - CFunctionPointer), - SILCoroutineKind::None, - ParameterConvention::Direct_Unowned, - SILParameterInfo(anyObjectMetaTy, - ParameterConvention::Direct_Unowned), - /*yields*/ {}, - SILResultInfo(OptNSStringTy, - ResultConvention::Autoreleased), - /*error result*/ None, - SubstitutionMap(), false, - ctx); + auto paramConvention = ParameterConvention::Direct_Unowned; + auto params = {SILParameterInfo(anyObjectMetaTy, paramConvention)}; + ArrayRef resultInfos = + {SILResultInfo(OptNSStringTy, ResultConvention::Autoreleased)}; + auto incompleteExtInfo = SILFunctionType::ExtInfo(); + auto repr = SILFunctionType::Representation::CFunctionPointer; + auto *clangFnType = ctx.getCanonicalClangFunctionType(params, + resultInfos[0], incompleteExtInfo, repr); + auto extInfo = incompleteExtInfo.withRepresentation(repr) + .withClangFunctionType(clangFnType); + + auto NSStringFromClassType = SILFunctionType::get( + nullptr, extInfo, SILCoroutineKind::None, paramConvention, params, + /*yields*/ {}, resultInfos, /*error result*/ None, SubstitutionMap(), + false, ctx); auto NSStringFromClassFn = builder.getOrCreateFunction( mainClass, "NSStringFromClass", SILLinkage::PublicExternal, NSStringFromClassType, IsBare, IsTransparent, IsNotSerialized, diff --git a/lib/Sema/TypeCheckType.cpp b/lib/Sema/TypeCheckType.cpp index 3cc68bf07d601..06a46cd75c70e 100644 --- a/lib/Sema/TypeCheckType.cpp +++ b/lib/Sema/TypeCheckType.cpp @@ -1814,8 +1814,12 @@ namespace { TypeResolutionOptions options, SILCoroutineKind coroutineKind = SILCoroutineKind::None, - SILFunctionType::ExtInfo extInfo + SILFunctionType::ExtInfo incompleteExtInfo = SILFunctionType::ExtInfo(), + SILFunctionType::Representation representation + = SILFunctionType::Representation::Thick, + const clang::Type *parsedClangType + = nullptr, ParameterConvention calleeConvention = DefaultParameterConvention, TypeRepr *witnessmethodProtocol = nullptr); @@ -2265,13 +2269,14 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs, : DifferentiabilityKind::Normal; } - // Resolve the function type directly with these attributes. - // TODO: [store-sil-clang-function-type] - SILFunctionType::ExtInfo extInfo(rep, attrs.has(TAK_pseudogeneric), - attrs.has(TAK_noescape), diffKind, - nullptr); + SILFunctionType::ExtInfo incompleteExtInfo( + SILFunctionType::Representation::Thick, + attrs.has(TAK_pseudogeneric), attrs.has(TAK_noescape), diffKind, + /*clangFunctionType*/ nullptr); - ty = resolveSILFunctionType(fnRepr, options, coroutineKind, extInfo, + ty = resolveSILFunctionType(fnRepr, options, coroutineKind, + incompleteExtInfo, rep, + /*parsedClangType*/nullptr, calleeConvention, witnessMethodProtocol); if (!ty || ty->hasError()) return ty; @@ -2772,12 +2777,15 @@ Type TypeResolver::resolveSILBoxType(SILBoxTypeRepr *repr, return SILBoxType::get(Context, layout, subMap); } -Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr, - TypeResolutionOptions options, - SILCoroutineKind coroutineKind, - SILFunctionType::ExtInfo extInfo, - ParameterConvention callee, - TypeRepr *witnessMethodProtocol) { +Type TypeResolver::resolveSILFunctionType( + FunctionTypeRepr *repr, + TypeResolutionOptions options, + SILCoroutineKind coroutineKind, + SILFunctionType::ExtInfo incompleteExtInfo, + SILFunctionType::Representation representation, + const clang::Type *parsedClangType, + ParameterConvention callee, + TypeRepr *witnessMethodProtocol) { options.setContext(None); bool hasError = false; @@ -2922,6 +2930,20 @@ Type TypeResolver::resolveSILFunctionType(FunctionTypeRepr *repr, "found witness_method without matching conformance"); } + const clang::Type *clangFnType = parsedClangType; + if ((representation == SILFunctionType::Representation::CFunctionPointer) + && !clangFnType) { + assert(results.size() <= 1 && yields.size() == 0 + && "@convention(c) functions have at most 1 result and 0 yields."); + auto result = results.empty() ? Optional() : results[0]; + clangFnType = Context.getCanonicalClangFunctionType(interfaceParams, result, + incompleteExtInfo, + representation); + } + + auto extInfo = incompleteExtInfo.withRepresentation(representation) + .withClangFunctionType(clangFnType); + return SILFunctionType::get(genericSig, extInfo, coroutineKind, callee, interfaceParams, interfaceYields, From a27c5f0a161b344219ddb5736f7fbd034b6908fe Mon Sep 17 00:00:00 2001 From: Varun Gandhi Date: Wed, 15 Jan 2020 16:15:44 -0800 Subject: [PATCH 5/5] [Printer] Conditionally print Clang types in emitted SIL. Hopefully, this helps us debug Clang type mismatches better. --- include/swift/AST/PrintOptions.h | 5 ++++- include/swift/AST/SILOptions.h | 3 +++ include/swift/Frontend/FrontendOptions.h | 3 +++ .../swift/Frontend/ModuleInterfaceSupport.h | 4 ++-- include/swift/Option/FrontendOptions.td | 6 ++++-- include/swift/SIL/SILModule.h | 7 ++++--- include/swift/SIL/SILPrintContext.h | 12 +++++++++++ include/swift/SIL/SILType.h | 3 ++- .../ArgsToFrontendOptionsConverter.cpp | 2 ++ lib/Frontend/CompilerInvocation.cpp | 2 ++ lib/FrontendTool/FrontendTool.cpp | 11 +++++----- lib/SIL/SILPrinter.cpp | 19 ++++++++++++------ test/SIL/clang-function-types.swift | 8 ++++++++ .../SILFunctionExtractor.cpp | 20 +++++++++++-------- tools/sil-opt/SILOpt.cpp | 18 +++++++++-------- 15 files changed, 86 insertions(+), 37 deletions(-) create mode 100644 test/SIL/clang-function-types.swift diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index aa5ec2a051b4b..bae5a918a1942 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -564,7 +564,7 @@ struct PrintOptions { static PrintOptions printDocInterface(); /// Retrieve the set of options suitable for printing SIL functions. - static PrintOptions printSIL() { + static PrintOptions printSIL(bool printFullConvention = false) { PrintOptions result; result.PrintLongAttrsOnSeparateLines = true; result.PrintStorageRepresentationAttrs = true; @@ -575,6 +575,9 @@ struct PrintOptions { result.PrintIfConfig = false; result.OpaqueReturnTypePrinting = OpaqueReturnTypePrintingMode::StableReference; + if (printFullConvention) + result.PrintFunctionRepresentationAttrs = + PrintOptions::FunctionRepresentationMode::Full; return result; } diff --git a/include/swift/AST/SILOptions.h b/include/swift/AST/SILOptions.h index 31344711acc8f..03c2d19e1dbe9 100644 --- a/include/swift/AST/SILOptions.h +++ b/include/swift/AST/SILOptions.h @@ -78,6 +78,9 @@ class SILOptions { /// variables by name when we print it out. This eases diffing of SIL files. bool EmitSortedSIL = false; + /// See \ref FrontendOptions.PrintFullConvention + bool PrintFullConvention = false; + /// Whether to stop the optimization pipeline after serializing SIL. bool StopOptimizationAfterSerialization = false; diff --git a/include/swift/Frontend/FrontendOptions.h b/include/swift/Frontend/FrontendOptions.h index b68d805d9833d..bf8b805eb333e 100644 --- a/include/swift/Frontend/FrontendOptions.h +++ b/include/swift/Frontend/FrontendOptions.h @@ -253,6 +253,9 @@ class FrontendOptions { /// See the \ref SILOptions.EmitSortedSIL flag. bool EmitSortedSIL = false; + /// Should we emit the cType when printing @convention(c) or no? + bool PrintFullConvention = false; + /// Indicates whether the dependency tracker should track system /// dependencies as well. bool TrackSystemDeps = false; diff --git a/include/swift/Frontend/ModuleInterfaceSupport.h b/include/swift/Frontend/ModuleInterfaceSupport.h index 4289150c14554..44077eb95ecfe 100644 --- a/include/swift/Frontend/ModuleInterfaceSupport.h +++ b/include/swift/Frontend/ModuleInterfaceSupport.h @@ -31,8 +31,8 @@ struct ModuleInterfaceOptions { /// interface, or should we fully-qualify them? bool PreserveTypesAsWritten = false; - /// Should we emit the cType when printing @convention(c) or no? - /// FIXME: [clang-function-type-serialization] This check should go away. + /// See \ref FrontendOptions.PrintFullConvention. + /// FIXME: [clang-function-type-serialization] This flag should go away. bool PrintFullConvention = false; /// Copy of all the command-line flags passed at .swiftinterface diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td index a5d369df049b5..61468a2146421 100644 --- a/include/swift/Option/FrontendOptions.td +++ b/include/swift/Option/FrontendOptions.td @@ -608,10 +608,12 @@ def module_interface_preserve_types_as_written : HelpText<"When emitting a module interface, preserve types as they were " "written in the source">; +// FIXME: [clang-function-type-serialization] Make this a SIL-only option once we +// start unconditionally emitting non-canonical Clang types in swiftinterfaces. def experimental_print_full_convention : Flag<["-"], "experimental-print-full-convention">, - HelpText<"When emitting a module interface, emit additional @convention " - "arguments, regardless of whether they were written in the source">; + HelpText<"When emitting a module interface or SIL, emit additional @convention" + " arguments, regardless of whether they were written in the source">; def prebuilt_module_cache_path : Separate<["-"], "prebuilt-module-cache-path">, diff --git a/include/swift/SIL/SILModule.h b/include/swift/SIL/SILModule.h index d72b69a29e209..2230aaaca3e70 100644 --- a/include/swift/SIL/SILModule.h +++ b/include/swift/SIL/SILModule.h @@ -647,10 +647,11 @@ class SILModule { /// \param ShouldSort If set to true sorts functions, vtables, sil global /// variables, and witness tables by name to ease diffing. /// \param PrintASTDecls If set to true print AST decls. - void print(raw_ostream &OS, bool Verbose = false, - ModuleDecl *M = nullptr, bool ShouldSort = false, + void print(raw_ostream &OS, + ModuleDecl *M = nullptr, + const SILOptions &Opts = SILOptions(), bool PrintASTDecls = true) const { - SILPrintContext PrintCtx(OS, Verbose, ShouldSort); + SILPrintContext PrintCtx(OS, Opts); print(PrintCtx, M, PrintASTDecls); } diff --git a/include/swift/SIL/SILPrintContext.h b/include/swift/SIL/SILPrintContext.h index b213bdc2a05e6..7f0f244875443 100644 --- a/include/swift/SIL/SILPrintContext.h +++ b/include/swift/SIL/SILPrintContext.h @@ -13,6 +13,7 @@ #ifndef SWIFT_SIL_PRINTCONTEXT_H #define SWIFT_SIL_PRINTCONTEXT_H +#include "swift/AST/SILOptions.h" #include "swift/SIL/SILDebugScope.h" #include "swift/SIL/SILValue.h" #include "llvm/ADT/DenseMap.h" @@ -65,6 +66,9 @@ class SILPrintContext { /// Print debug locations and scopes. bool DebugInfo; + /// See \ref FrontendOptions.PrintFullConvention. + bool PrintFullConvention; + public: /// Constructor with default values for options. /// @@ -72,6 +76,11 @@ class SILPrintContext { SILPrintContext(llvm::raw_ostream &OS, bool Verbose = false, bool SortedSIL = false); + /// Constructor based on SILOptions. + /// + /// DebugInfo will be set according to the -sil-print-debuginfo option. + SILPrintContext(llvm::raw_ostream &OS, const SILOptions &Opts); + SILPrintContext(llvm::raw_ostream &OS, bool Verbose, bool SortedSIL, bool DebugInfo); @@ -94,6 +103,9 @@ class SILPrintContext { /// Returns true if debug locations and scopes should be printed. bool printDebugInfo() const { return DebugInfo; } + /// Returns true if the entire @convention(c, cType: ..) should be printed. + bool printFullConvention() const { return PrintFullConvention; } + SILPrintContext::ID getID(const SILBasicBlock *Block); SILPrintContext::ID getID(const SILNode *node); diff --git a/include/swift/SIL/SILType.h b/include/swift/SIL/SILType.h index 0159b23b41ab6..30a59a3ab9127 100644 --- a/include/swift/SIL/SILType.h +++ b/include/swift/SIL/SILType.h @@ -581,7 +581,8 @@ class SILType { std::string getAsString() const; void dump() const; - void print(raw_ostream &OS) const; + void print(raw_ostream &OS, + const PrintOptions &PO = PrintOptions::printSIL()) const; }; // Statically prevent SILTypes from being directly cast to a type diff --git a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp index 0958d6df7b64d..6acc124c80774 100644 --- a/lib/Frontend/ArgsToFrontendOptionsConverter.cpp +++ b/lib/Frontend/ArgsToFrontendOptionsConverter.cpp @@ -68,6 +68,8 @@ bool ArgsToFrontendOptionsConverter::convert( Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil); Opts.EmitSortedSIL |= Args.hasArg(OPT_emit_sorted_sil); + Opts.PrintFullConvention |= + Args.hasArg(OPT_experimental_print_full_convention); Opts.EnableTesting |= Args.hasArg(OPT_enable_testing); Opts.EnablePrivateImports |= Args.hasArg(OPT_enable_private_imports); diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index b8eb1b23b75e5..dbe9733e670ab 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -942,6 +942,8 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args, Opts.DebugSerialization |= Args.hasArg(OPT_sil_debug_serialization); Opts.EmitVerboseSIL |= Args.hasArg(OPT_emit_verbose_sil); Opts.EmitSortedSIL |= Args.hasArg(OPT_emit_sorted_sil); + Opts.PrintFullConvention |= + Args.hasArg(OPT_experimental_print_full_convention); Opts.PrintInstCounts |= Args.hasArg(OPT_print_inst_counts); if (const Arg *A = Args.getLastArg(OPT_external_pass_pipeline_filename)) Opts.ExternalPassPipelineFilename = A->getValue(); diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp index 74b9114c458b8..0673a6238cce5 100644 --- a/lib/FrontendTool/FrontendTool.cpp +++ b/lib/FrontendTool/FrontendTool.cpp @@ -499,20 +499,19 @@ static bool emitSyntax(SourceFile *SF, StringRef OutputFilename) { } /// Writes SIL out to the given file. -static bool writeSIL(SILModule &SM, ModuleDecl *M, bool EmitVerboseSIL, - StringRef OutputFilename, bool SortSIL) { +static bool writeSIL(SILModule &SM, ModuleDecl *M, const SILOptions &Opts, + StringRef OutputFilename) { auto OS = getFileOutputStream(OutputFilename, M->getASTContext()); if (!OS) return true; - SM.print(*OS, EmitVerboseSIL, M, SortSIL); + SM.print(*OS, M, Opts); return M->getASTContext().hadError(); } static bool writeSIL(SILModule &SM, const PrimarySpecificPaths &PSPs, const CompilerInstance &Instance, - const SILOptions &opts) { - return writeSIL(SM, Instance.getMainModule(), opts.EmitVerboseSIL, - PSPs.OutputFilename, opts.EmitSortedSIL); + const SILOptions &Opts) { + return writeSIL(SM, Instance.getMainModule(), Opts, PSPs.OutputFilename); } /// Prints the Objective-C "generated header" interface for \p M to \p diff --git a/lib/SIL/SILPrinter.cpp b/lib/SIL/SILPrinter.cpp index 9f8c16d5aeb4a..bd3d267fb216b 100644 --- a/lib/SIL/SILPrinter.cpp +++ b/lib/SIL/SILPrinter.cpp @@ -419,12 +419,11 @@ static void printSILTypeColorAndSigil(raw_ostream &OS, SILType t) { ::print(OS, t.getCategory()); } -void SILType::print(raw_ostream &OS) const { +void SILType::print(raw_ostream &OS, const PrintOptions &PO) const { printSILTypeColorAndSigil(OS, *this); // Print other types as their Swift representation. - PrintOptions SubPrinter = PrintOptions::printSIL(); - getASTType().print(OS, SubPrinter); + getASTType().print(OS, PO); } void SILType::dump() const { @@ -493,7 +492,8 @@ class SILPrinter : public SILInstructionVisitor { SILPrintContext &PrintCtx, llvm::DenseMap *AlternativeTypeNames = nullptr) : Ctx(PrintCtx), - PrintState{{PrintCtx.OS()}, PrintOptions::printSIL()}, + PrintState{{PrintCtx.OS()}, + PrintOptions::printSIL(PrintCtx.printFullConvention())}, LastBufferID(0) { PrintState.ASTOptions.AlternativeTypeNames = AlternativeTypeNames; PrintState.ASTOptions.PrintForSIL = true; @@ -2449,7 +2449,8 @@ void SILFunction::print(SILPrintContext &PrintCtx) const { } { - PrintOptions withGenericEnvironment = PrintOptions::printSIL(); + PrintOptions withGenericEnvironment = + PrintOptions::printSIL(PrintCtx.printFullConvention()); withGenericEnvironment.GenericEnv = env; withGenericEnvironment.AlternativeTypeNames = Aliases.empty() ? nullptr : &Aliases; @@ -2732,7 +2733,8 @@ void SILModule::print(SILPrintContext &PrintCtx, ModuleDecl *M, // Print the declarations and types from the associated context (origin module or // current file). if (M && PrintASTDecls) { - PrintOptions Options = PrintOptions::printSIL(); + PrintOptions Options = + PrintOptions::printSIL(PrintCtx.printFullConvention()); Options.TypeDefinitions = true; Options.VarInitializers = true; // FIXME: ExplodePatternBindingDecls is incompatible with VarInitializers! @@ -3116,6 +3118,11 @@ SILPrintContext::SILPrintContext(llvm::raw_ostream &OS, bool Verbose, OutStream(OS), Verbose(Verbose), SortedSIL(SortedSIL), DebugInfo(SILPrintDebugInfo) { } +SILPrintContext::SILPrintContext(llvm::raw_ostream &OS, + const SILOptions &Opts) : + OutStream(OS), Verbose(Opts.EmitVerboseSIL), SortedSIL(Opts.EmitSortedSIL), + DebugInfo(SILPrintDebugInfo), PrintFullConvention(Opts.PrintFullConvention) {} + SILPrintContext::SILPrintContext(llvm::raw_ostream &OS, bool Verbose, bool SortedSIL, bool DebugInfo) : OutStream(OS), Verbose(Verbose), SortedSIL(SortedSIL), diff --git a/test/SIL/clang-function-types.swift b/test/SIL/clang-function-types.swift new file mode 100644 index 0000000000000..6ed5268a9268a --- /dev/null +++ b/test/SIL/clang-function-types.swift @@ -0,0 +1,8 @@ +// RUN: %target-swift-frontend %s -emit-sil -swift-version 5 -use-clang-function-types -experimental-print-full-convention -o - | %FileCheck %s + +public func f(g: @convention(c) () -> ()) { g() } + +// CHECK: sil @$s4main1f1gyyyXC_tF : $@convention(thin) (@convention(c, cType: "void (*)(void)") @noescape () -> ()) -> () { +// CHECK: bb0(%0 : $@convention(c, cType: "void (*)(void)") @noescape () -> ()): +// CHECK: debug_value %0 : $@convention(c, cType: "void (*)(void)") @noescape () -> (), let, name "g", argno 1 // id: %1 +// CHECK: %2 = apply %0() : $@convention(c, cType: "void (*)(void)") @noescape () -> () diff --git a/tools/sil-func-extractor/SILFunctionExtractor.cpp b/tools/sil-func-extractor/SILFunctionExtractor.cpp index 7c04d529c33fa..c1442d7bf6e6a 100644 --- a/tools/sil-func-extractor/SILFunctionExtractor.cpp +++ b/tools/sil-func-extractor/SILFunctionExtractor.cpp @@ -101,10 +101,10 @@ static llvm::cl::opt Triple("target", llvm::cl::desc("target triple")); static llvm::cl::opt -EnableSILSortOutput("emit-sorted-sil", llvm::cl::Hidden, - llvm::cl::init(false), - llvm::cl::desc("Sort Functions, VTables, Globals, " - "WitnessTables by name to ease diffing.")); +EmitSortedSIL("emit-sorted-sil", llvm::cl::Hidden, + llvm::cl::init(false), + llvm::cl::desc("Sort Functions, VTables, Globals, " + "WitnessTables by name to ease diffing.")); static llvm::cl::opt DisableASTDump("sil-disable-ast-dump", llvm::cl::Hidden, @@ -250,6 +250,10 @@ int main(int argc, char **argv) { Invocation.getLangOptions().EnableAccessControl = false; Invocation.getLangOptions().EnableObjCAttrRequiresFoundation = false; + SILOptions &Opts = Invocation.getSILOptions(); + Opts.EmitVerboseSIL = EmitVerboseSIL; + Opts.EmitSortedSIL = EmitSortedSIL; + serialization::ExtendedValidationInfo extendedInfo; llvm::ErrorOr> FileBufOrErr = Invocation.setUpInputForSILTool(InputFilename, ModuleName, @@ -356,8 +360,8 @@ int main(int argc, char **argv) { OutputFilename.size() ? StringRef(OutputFilename) : "-"; if (OutputFile == "-") { - CI.getSILModule()->print(llvm::outs(), EmitVerboseSIL, CI.getMainModule(), - EnableSILSortOutput, !DisableASTDump); + CI.getSILModule()->print(llvm::outs(), CI.getMainModule(), + Invocation.getSILOptions(), !DisableASTDump); } else { std::error_code EC; llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None); @@ -366,8 +370,8 @@ int main(int argc, char **argv) { << '\n'; return 1; } - CI.getSILModule()->print(OS, EmitVerboseSIL, CI.getMainModule(), - EnableSILSortOutput, !DisableASTDump); + CI.getSILModule()->print(OS, CI.getMainModule(), + Invocation.getSILOptions(), !DisableASTDump); } } } diff --git a/tools/sil-opt/SILOpt.cpp b/tools/sil-opt/SILOpt.cpp index 3cb447a96994b..59a0609e61ef3 100644 --- a/tools/sil-opt/SILOpt.cpp +++ b/tools/sil-opt/SILOpt.cpp @@ -196,10 +196,10 @@ static llvm::cl::opt ModuleCachePath("module-cache-path", llvm::cl::desc("Clang module cache path")); static llvm::cl::opt -EnableSILSortOutput("emit-sorted-sil", llvm::cl::Hidden, - llvm::cl::init(false), - llvm::cl::desc("Sort Functions, VTables, Globals, " - "WitnessTables by name to ease diffing.")); +EmitSortedSIL("emit-sorted-sil", llvm::cl::Hidden, + llvm::cl::init(false), + llvm::cl::desc("Sort Functions, VTables, Globals, " + "WitnessTables by name to ease diffing.")); static llvm::cl::opt DisableASTDump("sil-disable-ast-dump", llvm::cl::Hidden, @@ -375,6 +375,8 @@ int main(int argc, char **argv) { break; } } + SILOpts.EmitVerboseSIL |= EmitVerboseSIL; + SILOpts.EmitSortedSIL |= EmitSortedSIL; serialization::ExtendedValidationInfo extendedInfo; llvm::ErrorOr> FileBufOrErr = @@ -481,8 +483,8 @@ int main(int argc, char **argv) { StringRef(OutputFilename) : "-"; if (OutputFile == "-") { - CI.getSILModule()->print(llvm::outs(), EmitVerboseSIL, CI.getMainModule(), - EnableSILSortOutput, !DisableASTDump); + CI.getSILModule()->print(llvm::outs(), CI.getMainModule(), + Invocation.getSILOptions(), !DisableASTDump); } else { std::error_code EC; llvm::raw_fd_ostream OS(OutputFile, EC, llvm::sys::fs::F_None); @@ -491,8 +493,8 @@ int main(int argc, char **argv) { << EC.message() << '\n'; return 1; } - CI.getSILModule()->print(OS, EmitVerboseSIL, CI.getMainModule(), - EnableSILSortOutput, !DisableASTDump); + CI.getSILModule()->print(OS, CI.getMainModule(), + Invocation.getSILOptions(), !DisableASTDump); } }