Skip to content

Commit 7b967a8

Browse files
Merge pull request #33085 from varungandhi-apple/vg-clang-types-in-sil-retry
Propagate Clang function types through SIL
2 parents 007c814 + 983399c commit 7b967a8

38 files changed

+685
-336
lines changed

include/swift/AST/ExtInfo.h

Lines changed: 106 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class FunctionType;
4141
class SILExtInfo;
4242
class SILExtInfoBuilder;
4343
class SILFunctionType;
44+
enum class SILFunctionTypeRepresentation : uint8_t;
4445
} // namespace swift
4546

4647
namespace swift {
@@ -54,6 +55,7 @@ class ClangTypeInfo {
5455
friend ASTExtInfoBuilder;
5556
friend SILExtInfoBuilder;
5657

58+
// [NOTE: ClangTypeInfo-contents]
5759
// We preserve a full clang::Type *, not a clang::FunctionType * as:
5860
// 1. We need to keep sugar in case we need to present an error to the user
5961
// (for AnyFunctionType).
@@ -81,6 +83,26 @@ class ClangTypeInfo {
8183
void dump(llvm::raw_ostream &os, const clang::ASTContext &ctx) const;
8284
};
8385

86+
// MARK: - UnexpectedClangTypeError
87+
/// Potential errors when trying to store a Clang type in an ExtInfo.
88+
struct UnexpectedClangTypeError {
89+
enum class Kind {
90+
NullForCOrBlock,
91+
NonnullForNonCOrBlock,
92+
NotBlockPointer,
93+
NotFunctionPointerOrReference,
94+
NonCanonical,
95+
};
96+
const Kind errorKind;
97+
const clang::Type *type;
98+
99+
static Optional<UnexpectedClangTypeError> checkClangType(
100+
SILFunctionTypeRepresentation fnRep, const clang::Type *type,
101+
bool expectNonnullForCOrBlock, bool expectCanonical);
102+
103+
void dump();
104+
};
105+
84106
// MARK: - FunctionTypeRepresentation
85107
/// The representation form of a function.
86108
enum class FunctionTypeRepresentation : uint8_t {
@@ -146,6 +168,41 @@ enum class SILFunctionTypeRepresentation : uint8_t {
146168
Closure,
147169
};
148170

171+
constexpr SILFunctionTypeRepresentation
172+
convertRepresentation(FunctionTypeRepresentation rep) {
173+
switch (rep) {
174+
case FunctionTypeRepresentation::Swift:
175+
return SILFunctionTypeRepresentation::Thick;
176+
case FunctionTypeRepresentation::Block:
177+
return SILFunctionTypeRepresentation::Block;
178+
case FunctionTypeRepresentation::Thin:
179+
return SILFunctionTypeRepresentation::Thin;
180+
case FunctionTypeRepresentation::CFunctionPointer:
181+
return SILFunctionTypeRepresentation::CFunctionPointer;
182+
}
183+
llvm_unreachable("Unhandled FunctionTypeRepresentation!");
184+
};
185+
186+
inline Optional<FunctionTypeRepresentation>
187+
convertRepresentation(SILFunctionTypeRepresentation rep) {
188+
switch (rep) {
189+
case SILFunctionTypeRepresentation::Thick:
190+
return {FunctionTypeRepresentation::Swift};
191+
case SILFunctionTypeRepresentation::Block:
192+
return {FunctionTypeRepresentation::Block};
193+
case SILFunctionTypeRepresentation::Thin:
194+
return {FunctionTypeRepresentation::Thin};
195+
case SILFunctionTypeRepresentation::CFunctionPointer:
196+
return {FunctionTypeRepresentation::CFunctionPointer};
197+
case SILFunctionTypeRepresentation::Method:
198+
case SILFunctionTypeRepresentation::ObjCMethod:
199+
case SILFunctionTypeRepresentation::WitnessMethod:
200+
case SILFunctionTypeRepresentation::Closure:
201+
return None;
202+
}
203+
llvm_unreachable("Unhandled SILFunctionTypeRepresentation!");
204+
};
205+
149206
/// Can this calling convention result in a function being called indirectly
150207
/// through the runtime.
151208
constexpr bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) {
@@ -165,6 +222,25 @@ constexpr bool canBeCalledIndirectly(SILFunctionTypeRepresentation rep) {
165222
llvm_unreachable("Unhandled SILFunctionTypeRepresentation in switch.");
166223
}
167224

225+
template <typename Repr> constexpr bool shouldStoreClangType(Repr repr) {
226+
static_assert(std::is_same<Repr, FunctionTypeRepresentation>::value ||
227+
std::is_same<Repr, SILFunctionTypeRepresentation>::value,
228+
"Expected a Representation type as the argument type.");
229+
switch (static_cast<SILFunctionTypeRepresentation>(repr)) {
230+
case SILFunctionTypeRepresentation::CFunctionPointer:
231+
case SILFunctionTypeRepresentation::Block:
232+
return true;
233+
case SILFunctionTypeRepresentation::ObjCMethod:
234+
case SILFunctionTypeRepresentation::Thick:
235+
case SILFunctionTypeRepresentation::Thin:
236+
case SILFunctionTypeRepresentation::Method:
237+
case SILFunctionTypeRepresentation::WitnessMethod:
238+
case SILFunctionTypeRepresentation::Closure:
239+
return false;
240+
}
241+
llvm_unreachable("Unhandled SILFunctionTypeRepresentation.");
242+
}
243+
168244
// MARK: - ASTExtInfoBuilder
169245
/// A builder type for creating an \c ASTExtInfo.
170246
///
@@ -292,7 +368,8 @@ class ASTExtInfoBuilder {
292368
LLVM_NODISCARD
293369
ASTExtInfoBuilder withRepresentation(Representation rep) const {
294370
return ASTExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep,
295-
clangTypeInfo);
371+
shouldStoreClangType(rep) ? clangTypeInfo
372+
: ClangTypeInfo());
296373
}
297374
LLVM_NODISCARD
298375
ASTExtInfoBuilder withNoEscape(bool noEscape = true) const {
@@ -333,7 +410,8 @@ class ASTExtInfoBuilder {
333410
ASTExtInfoBuilder
334411
withSILRepresentation(SILFunctionTypeRepresentation rep) const {
335412
return ASTExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep,
336-
clangTypeInfo);
413+
shouldStoreClangType(rep) ? clangTypeInfo
414+
: ClangTypeInfo());
337415
}
338416

339417
bool isEqualTo(ASTExtInfoBuilder other, bool useClangTypes) const {
@@ -360,12 +438,16 @@ class ASTExtInfo {
360438

361439
ASTExtInfoBuilder builder;
362440

441+
// Only for use by ASTExtInfoBuilder::build. Don't use it elsewhere!
363442
ASTExtInfo(ASTExtInfoBuilder builder) : builder(builder) {}
443+
364444
ASTExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo)
365-
: builder(bits, clangTypeInfo){};
445+
: builder(bits, clangTypeInfo) {
446+
builder.checkInvariants();
447+
};
366448

367449
public:
368-
ASTExtInfo() : builder(){};
450+
ASTExtInfo() : builder() { builder.checkInvariants(); };
369451

370452
/// Create a builder with the same state as \c this.
371453
ASTExtInfoBuilder intoBuilder() const { return builder; }
@@ -504,7 +586,7 @@ class SILExtInfoBuilder {
504586
using Representation = SILFunctionTypeRepresentation;
505587

506588
SILExtInfoBuilder(unsigned bits, ClangTypeInfo clangTypeInfo)
507-
: bits(bits), clangTypeInfo(clangTypeInfo) {}
589+
: bits(bits), clangTypeInfo(clangTypeInfo.getCanonical()) {}
508590

509591
static constexpr unsigned makeBits(Representation rep, bool isPseudogeneric,
510592
bool isNoEscape, bool isAsync,
@@ -606,7 +688,8 @@ class SILExtInfoBuilder {
606688
// the following with methods instead of mutating these objects.
607689
SILExtInfoBuilder withRepresentation(Representation rep) const {
608690
return SILExtInfoBuilder((bits & ~RepresentationMask) | (unsigned)rep,
609-
clangTypeInfo);
691+
shouldStoreClangType(rep) ? clangTypeInfo
692+
: ClangTypeInfo());
610693
}
611694
SILExtInfoBuilder withIsPseudogeneric(bool isPseudogeneric = true) const {
612695
return SILExtInfoBuilder(isPseudogeneric ? (bits | PseudogenericMask)
@@ -629,6 +712,10 @@ class SILExtInfoBuilder {
629712
((unsigned)differentiability << DifferentiabilityMaskOffset),
630713
clangTypeInfo);
631714
}
715+
LLVM_NODISCARD
716+
SILExtInfoBuilder withClangFunctionType(const clang::Type *type) const {
717+
return SILExtInfoBuilder(bits, ClangTypeInfo(type).getCanonical());
718+
}
632719

633720
bool isEqualTo(SILExtInfoBuilder other, bool useClangTypes) const {
634721
return bits == other.bits &&
@@ -654,12 +741,21 @@ class SILExtInfo {
654741

655742
SILExtInfoBuilder builder;
656743

744+
// Only for use by SILExtInfoBuilder::build. Don't use it elsewhere!
657745
SILExtInfo(SILExtInfoBuilder builder) : builder(builder) {}
746+
658747
SILExtInfo(unsigned bits, ClangTypeInfo clangTypeInfo)
659-
: builder(bits, clangTypeInfo){};
748+
: builder(bits, clangTypeInfo) {
749+
builder.checkInvariants();
750+
};
660751

661752
public:
662-
SILExtInfo() : builder(){};
753+
SILExtInfo() : builder() { builder.checkInvariants(); };
754+
755+
SILExtInfo(ASTExtInfo info, bool isPseudogeneric)
756+
: builder(info.intoBuilder(), isPseudogeneric) {
757+
builder.checkInvariants();
758+
}
663759

664760
static SILExtInfo getThin() {
665761
return SILExtInfoBuilder(SILExtInfoBuilder::Representation::Thin, false,
@@ -722,6 +818,8 @@ class SILExtInfo {
722818
constexpr std::pair<unsigned, const void *> getFuncAttrKey() const {
723819
return builder.getFuncAttrKey();
724820
}
821+
822+
Optional<UnexpectedClangTypeError> checkClangType() const;
725823
};
726824

727825
/// Helper function to obtain the useClangTypes parameter for checking equality

include/swift/AST/PrintOptions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ struct PrintOptions {
594594
static PrintOptions printDocInterface();
595595

596596
/// Retrieve the set of options suitable for printing SIL functions.
597-
static PrintOptions printSIL() {
597+
static PrintOptions printSIL(bool printFullConvention = false) {
598598
PrintOptions result;
599599
result.PrintLongAttrsOnSeparateLines = true;
600600
result.PrintStorageRepresentationAttrs = true;
@@ -605,6 +605,9 @@ struct PrintOptions {
605605
result.PrintIfConfig = false;
606606
result.OpaqueReturnTypePrinting =
607607
OpaqueReturnTypePrintingMode::StableReference;
608+
if (printFullConvention)
609+
result.PrintFunctionRepresentationAttrs =
610+
PrintOptions::FunctionRepresentationMode::Full;
608611
return result;
609612
}
610613

include/swift/AST/SILOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class SILOptions {
7878
/// variables by name when we print it out. This eases diffing of SIL files.
7979
bool EmitSortedSIL = false;
8080

81+
/// See \ref FrontendOptions.PrintFullConvention
82+
bool PrintFullConvention = false;
83+
8184
/// Whether to stop the optimization pipeline after serializing SIL.
8285
bool StopOptimizationAfterSerialization = false;
8386

include/swift/AST/Types.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3888,7 +3888,7 @@ class SILFunctionType final
38883888
public llvm::FoldingSetNode,
38893889
private llvm::TrailingObjects<SILFunctionType, SILParameterInfo,
38903890
SILResultInfo, SILYieldInfo,
3891-
SubstitutionMap, CanType> {
3891+
SubstitutionMap, CanType, ClangTypeInfo> {
38923892
friend TrailingObjects;
38933893

38943894
size_t numTrailingObjects(OverloadToken<SILParameterInfo>) const {
@@ -3912,6 +3912,10 @@ class SILFunctionType final
39123912
size_t(hasInvocationSubstitutions());
39133913
}
39143914

3915+
size_t numTrailingObjects(OverloadToken<ClangTypeInfo>) const {
3916+
return Bits.SILFunctionType.HasClangTypeInfo ? 1 : 0;
3917+
}
3918+
39153919
public:
39163920
using ExtInfo = SILExtInfo;
39173921
using ExtInfoBuilder = SILExtInfoBuilder;

include/swift/Frontend/FrontendOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ class FrontendOptions {
244244
/// output path is configured.
245245
Optional<IntermoduleDepTrackingMode> IntermoduleDependencyTracking;
246246

247+
/// Should we emit the cType when printing @convention(c) or no?
248+
bool PrintFullConvention = false;
249+
247250
/// Should we serialize the hashes of dependencies (vs. the modification
248251
/// times) when compiling a module interface?
249252
bool SerializeModuleInterfaceDependencyHashes = false;

include/swift/Frontend/ModuleInterfaceSupport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct ModuleInterfaceOptions {
3232
/// interface, or should we fully-qualify them?
3333
bool PreserveTypesAsWritten = false;
3434

35-
/// Should we emit the cType when printing @convention(c) or no?
35+
/// See \ref FrontendOptions.PrintFullConvention.
3636
/// [TODO: Clang-type-plumbing] This check should go away.
3737
bool PrintFullConvention = false;
3838

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -664,10 +664,12 @@ def experimental_spi_imports :
664664
Flag<["-"], "experimental-spi-imports">,
665665
HelpText<"Enable experimental support for SPI imports">;
666666

667+
// [FIXME: Clang-type-plumbing] Make this a SIL-only option once we start
668+
// unconditionally emitting non-canonical Clang types in swiftinterfaces.
667669
def experimental_print_full_convention :
668670
Flag<["-"], "experimental-print-full-convention">,
669-
HelpText<"When emitting a module interface, emit additional @convention "
670-
"arguments, regardless of whether they were written in the source">;
671+
HelpText<"When emitting a module interface or SIL, emit additional @convention"
672+
" arguments, regardless of whether they were written in the source">;
671673

672674
def experimental_one_way_closure_params :
673675
Flag<["-"], "experimental-one-way-closure-params">,

include/swift/SIL/SILModule.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -681,8 +681,7 @@ class SILModule {
681681
/// \param Opts The SIL options, used to determine printing verbosity and
682682
/// and sorting.
683683
/// \param PrintASTDecls If set to true print AST decls.
684-
void print(raw_ostream& OS,
685-
ModuleDecl *M = nullptr,
684+
void print(raw_ostream &OS, ModuleDecl *M = nullptr,
686685
const SILOptions &Opts = SILOptions(),
687686
bool PrintASTDecls = true) const {
688687
SILPrintContext PrintCtx(OS, Opts);

include/swift/SIL/SILPrintContext.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,23 @@ class SILPrintContext {
6666
/// Print debug locations and scopes.
6767
bool DebugInfo;
6868

69+
/// See \ref FrontendOptions.PrintFullConvention.
70+
bool PrintFullConvention;
71+
6972
public:
7073
/// Constructor with default values for options.
7174
///
7275
/// DebugInfo will be set according to the -sil-print-debuginfo option.
7376
SILPrintContext(llvm::raw_ostream &OS, bool Verbose = false,
74-
bool SortedSIL = false);
77+
bool SortedSIL = false, bool PrintFullConvention = false);
7578

7679
/// Constructor based on SILOptions.
7780
///
7881
/// DebugInfo will be set according to the -sil-print-debuginfo option.
7982
SILPrintContext(llvm::raw_ostream &OS, const SILOptions &Opts);
8083

81-
SILPrintContext(llvm::raw_ostream &OS, bool Verbose,
82-
bool SortedSIL, bool DebugInfo);
84+
SILPrintContext(llvm::raw_ostream &OS, bool Verbose, bool SortedSIL,
85+
bool DebugInfo, bool PrintFullConvention);
8386

8487
virtual ~SILPrintContext();
8588

@@ -100,6 +103,9 @@ class SILPrintContext {
100103
/// Returns true if debug locations and scopes should be printed.
101104
bool printDebugInfo() const { return DebugInfo; }
102105

106+
/// Returns true if the entire @convention(c, cType: ..) should be printed.
107+
bool printFullConvention() const { return PrintFullConvention; }
108+
103109
SILPrintContext::ID getID(const SILBasicBlock *Block);
104110

105111
SILPrintContext::ID getID(const SILNode *node);

include/swift/SIL/SILType.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,8 @@ class SILType {
611611

612612
std::string getAsString() const;
613613
void dump() const;
614-
void print(raw_ostream &OS) const;
614+
void print(raw_ostream &OS,
615+
const PrintOptions &PO = PrintOptions::printSIL()) const;
615616
};
616617

617618
// Statically prevent SILTypes from being directly cast to a type

0 commit comments

Comments
 (0)