Skip to content

Commit c2b2f13

Browse files
committed
SIL representation
1 parent 71f46a4 commit c2b2f13

19 files changed

+129
-29
lines changed

include/swift/AST/Availability.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,9 @@ class AvailabilityInference {
316316
static Optional<AvailabilityContext> annotatedAvailableRange(const Decl *D,
317317
ASTContext &C);
318318

319+
static AvailabilityContext
320+
annotatedAvailableRangeForAttr(const SpecializeAttr* attr, ASTContext &ctx);
321+
319322
};
320323

321324
} // end namespace swift

include/swift/Parse/Parser.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,7 @@ class Parser {
10491049
/// \p Attr is where to store the parsed attribute
10501050
bool parseSpecializeAttribute(
10511051
swift::tok ClosingBrace, SourceLoc AtLoc, SourceLoc Loc,
1052-
SpecializeAttr *&Attr,
1052+
SpecializeAttr *&Attr, AvailabilityContext *SILAvailability,
10531053
llvm::function_ref<bool(Parser &)> parseSILTargetName =
10541054
[](Parser &) { return false; },
10551055
llvm::function_ref<bool(Parser &)> parseSILSIPModule =
@@ -1060,6 +1060,7 @@ class Parser {
10601060
swift::tok ClosingBrace, bool &DiscardAttribute, Optional<bool> &Exported,
10611061
Optional<SpecializeAttr::SpecializationKind> &Kind,
10621062
TrailingWhereClause *&TrailingWhereClause, DeclNameRef &targetFunction,
1063+
AvailabilityContext *SILAvailability,
10631064
SmallVectorImpl<Identifier> &spiGroups,
10641065
SmallVectorImpl<AvailableAttr *> &availableAttrs,
10651066
llvm::function_ref<bool(Parser &)> parseSILTargetName,

include/swift/SIL/SILFunction.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ class SILSpecializeAttr final {
7272
GenericSignature specializedSignature,
7373
bool exported, SpecializationKind kind,
7474
SILFunction *target, Identifier spiGroup,
75-
const ModuleDecl *spiModule);
75+
const ModuleDecl *spiModule,
76+
AvailabilityContext availability);
7677

7778
bool isExported() const {
7879
return exported;
@@ -110,20 +111,26 @@ class SILSpecializeAttr final {
110111
return spiModule;
111112
}
112113

114+
AvailabilityContext getAvailability() const {
115+
return availability;
116+
}
117+
113118
void print(llvm::raw_ostream &OS) const;
114119

115120
private:
116121
SpecializationKind kind;
117122
bool exported;
118123
GenericSignature specializedSignature;
119124
Identifier spiGroup;
125+
AvailabilityContext availability;
120126
const ModuleDecl *spiModule = nullptr;
121127
SILFunction *F = nullptr;
122128
SILFunction *targetFunction = nullptr;
123129

124130
SILSpecializeAttr(bool exported, SpecializationKind kind,
125131
GenericSignature specializedSignature, SILFunction *target,
126-
Identifier spiGroup, const ModuleDecl *spiModule);
132+
Identifier spiGroup, const ModuleDecl *spiModule,
133+
AvailabilityContext availability);
127134
};
128135

129136
/// SILFunction - A function body that has been lowered to SIL. This consists of

lib/AST/Availability.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,33 @@ AvailabilityInference::annotatedAvailableRange(const Decl *D, ASTContext &Ctx) {
176176
VersionRange::allGTE(bestAvailAttr->Introduced.getValue())};
177177
}
178178

179+
AvailabilityContext
180+
AvailabilityInference::annotatedAvailableRangeForAttr(const SpecializeAttr* attr,
181+
ASTContext &ctx) {
182+
183+
const AvailableAttr *bestAvailAttr = nullptr;
184+
185+
for (auto *availAttr : attr->getAvailabeAttrs()) {
186+
if (availAttr == nullptr || !availAttr->Introduced.hasValue() ||
187+
!availAttr->isActivePlatform(ctx) ||
188+
availAttr->isLanguageVersionSpecific() ||
189+
availAttr->isPackageDescriptionVersionSpecific()) {
190+
continue;
191+
}
192+
193+
if (isBetterThan(availAttr, bestAvailAttr))
194+
bestAvailAttr = availAttr;
195+
}
196+
197+
if (bestAvailAttr) {
198+
return AvailabilityContext{
199+
VersionRange::allGTE(bestAvailAttr->Introduced.getValue())
200+
};
201+
}
202+
203+
return AvailabilityContext::alwaysAvailable();
204+
}
205+
179206
AvailabilityContext AvailabilityInference::availableRange(const Decl *D,
180207
ASTContext &Ctx) {
181208
Optional<AvailabilityContext> AnnotatedRange =

lib/Parse/ParseDecl.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -582,10 +582,11 @@ bool Parser::parseSpecializeAttributeArguments(
582582
swift::tok ClosingBrace, bool &DiscardAttribute, Optional<bool> &Exported,
583583
Optional<SpecializeAttr::SpecializationKind> &Kind,
584584
swift::TrailingWhereClause *&TrailingWhereClause,
585-
DeclNameRef &targetFunction, SmallVectorImpl<Identifier> &spiGroups,
585+
DeclNameRef &targetFunction, AvailabilityContext *SILAvailability, SmallVectorImpl<Identifier> &spiGroups,
586586
SmallVectorImpl<AvailableAttr *> &availableAttrs,
587587
llvm::function_ref<bool(Parser &)> parseSILTargetName,
588588
llvm::function_ref<bool(Parser &)> parseSILSIPModule) {
589+
bool isSIL = SILAvailability != nullptr;
589590
SyntaxParsingContext ContentContext(SyntaxContext,
590591
SyntaxKind::SpecializeAttributeSpecList);
591592
// Parse optional "exported" and "kind" labeled parameters.
@@ -601,7 +602,8 @@ bool Parser::parseSpecializeAttributeArguments(
601602
: SyntaxKind::LabeledSpecializeEntry));
602603
if (ParamLabel != "exported" && ParamLabel != "kind" &&
603604
ParamLabel != "target" && ParamLabel != "spi" &&
604-
ParamLabel != "spiModule" && ParamLabel != "availability") {
605+
ParamLabel != "spiModule" && ParamLabel != "availability" &&
606+
(!isSIL || ParamLabel != "available")) {
605607
diagnose(Tok.getLoc(), diag::attr_specialize_unknown_parameter_name,
606608
ParamLabel);
607609
}
@@ -627,6 +629,15 @@ bool Parser::parseSpecializeAttributeArguments(
627629
diagnose(Tok.getLoc(), diag::attr_specialize_parameter_already_defined,
628630
ParamLabel);
629631
}
632+
if (ParamLabel == "available") {
633+
SourceRange range;
634+
llvm::VersionTuple version;
635+
if (parseVersionTuple(version, range,
636+
diag::sil_availability_expected_version))
637+
return false;
638+
639+
*SILAvailability = AvailabilityContext(VersionRange::allGTE(version));
640+
}
630641
if (ParamLabel == "availability") {
631642
SourceRange attrRange;
632643
auto Loc = Tok.getLoc();
@@ -877,7 +888,7 @@ bool Parser::parseAvailability(
877888

878889
bool Parser::parseSpecializeAttribute(
879890
swift::tok ClosingBrace, SourceLoc AtLoc, SourceLoc Loc,
880-
SpecializeAttr *&Attr,
891+
SpecializeAttr *&Attr, AvailabilityContext *SILAvailability,
881892
llvm::function_ref<bool(Parser &)> parseSILTargetName,
882893
llvm::function_ref<bool(Parser &)> parseSILSIPModule) {
883894
assert(ClosingBrace == tok::r_paren || ClosingBrace == tok::r_square);
@@ -896,7 +907,7 @@ bool Parser::parseSpecializeAttribute(
896907
SmallVector<AvailableAttr *, 4> availableAttrs;
897908
if (!parseSpecializeAttributeArguments(
898909
ClosingBrace, DiscardAttribute, exported, kind, trailingWhereClause,
899-
targetFunction, spiGroups, availableAttrs, parseSILTargetName,
910+
targetFunction, SILAvailability, spiGroups, availableAttrs, parseSILTargetName,
900911
parseSILSIPModule)) {
901912
return false;
902913
}
@@ -2588,7 +2599,7 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
25882599
return false;
25892600
}
25902601
SpecializeAttr *Attr;
2591-
if (!parseSpecializeAttribute(tok::r_paren, AtLoc, Loc, Attr))
2602+
if (!parseSpecializeAttribute(tok::r_paren, AtLoc, Loc, Attr, nullptr))
25922603
return false;
25932604

25942605
Attributes.add(Attr);

lib/SIL/IR/SILFunction.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@ STATISTIC(MaxBitfieldID, "Max value of SILFunction::currentBitfieldID");
4040
SILSpecializeAttr::SILSpecializeAttr(bool exported, SpecializationKind kind,
4141
GenericSignature specializedSig,
4242
SILFunction *target, Identifier spiGroup,
43-
const ModuleDecl *spiModule)
43+
const ModuleDecl *spiModule,
44+
AvailabilityContext availability)
4445
: kind(kind), exported(exported), specializedSignature(specializedSig),
45-
spiGroup(spiGroup), spiModule(spiModule), targetFunction(target) {
46+
spiGroup(spiGroup), availability(availability), spiModule(spiModule), targetFunction(target) {
4647
if (targetFunction)
4748
targetFunction->incrementRefCount();
4849
}
@@ -51,10 +52,11 @@ SILSpecializeAttr *
5152
SILSpecializeAttr::create(SILModule &M, GenericSignature specializedSig,
5253
bool exported, SpecializationKind kind,
5354
SILFunction *target, Identifier spiGroup,
54-
const ModuleDecl *spiModule) {
55+
const ModuleDecl *spiModule,
56+
AvailabilityContext availability) {
5557
void *buf = M.allocate(sizeof(SILSpecializeAttr), alignof(SILSpecializeAttr));
5658
return ::new (buf) SILSpecializeAttr(exported, kind, specializedSig, target,
57-
spiGroup, spiModule);
59+
spiGroup, spiModule, availability);
5860
}
5961

6062
void SILFunction::addSpecializeAttr(SILSpecializeAttr *Attr) {

lib/SIL/IR/SILFunctionBuilder.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,20 @@ void SILFunctionBuilder::addFunctionAttributes(
8080
if (hasSPI) {
8181
spiGroupIdent = spiGroups[0];
8282
}
83+
auto availability =
84+
AvailabilityInference::annotatedAvailableRangeForAttr(SA,
85+
M.getSwiftModule()->getASTContext());
8386
if (targetFunctionDecl) {
8487
SILDeclRef declRef(targetFunctionDecl, constant.kind, false);
8588
targetFunction = getOrCreateDeclaration(targetFunctionDecl, declRef);
8689
F->addSpecializeAttr(SILSpecializeAttr::create(
8790
M, SA->getSpecializedSignature(), SA->isExported(), kind,
8891
targetFunction, spiGroupIdent,
89-
attributedFuncDecl->getModuleContext()));
92+
attributedFuncDecl->getModuleContext(), availability));
9093
} else {
9194
F->addSpecializeAttr(SILSpecializeAttr::create(
9295
M, SA->getSpecializedSignature(), SA->isExported(), kind, nullptr,
93-
spiGroupIdent, attributedFuncDecl->getModuleContext()));
96+
spiGroupIdent, attributedFuncDecl->getModuleContext(), availability));
9497
}
9598
}
9699

lib/SIL/IR/SILPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3711,6 +3711,10 @@ void SILSpecializeAttr::print(llvm::raw_ostream &OS) const {
37113711
if (targetFunction) {
37123712
OS << "target: \"" << targetFunction->getName() << "\", ";
37133713
}
3714+
if (!availability.isAlwaysAvailable()) {
3715+
auto version = availability.getOSVersion().getLowerEndpoint();
3716+
OS << "available: " << version.getAsString() << ", ";
3717+
}
37143718
if (!requirements.empty()) {
37153719
OS << "where ";
37163720
SILFunction *F = getFunction();

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ namespace {
114114
SILFunction *target = nullptr;
115115
Identifier spiGroupID;
116116
ModuleDecl *spiModule;
117+
AvailabilityContext availability = AvailabilityContext::alwaysAvailable();
117118
};
118119

119120
class SILParser {
@@ -1092,9 +1093,9 @@ static bool parseDeclSILOptional(bool *isTransparent,
10921093
SpecializeAttr *Attr;
10931094
StringRef targetFunctionName;
10941095
ModuleDecl *module = nullptr;
1095-
1096+
AvailabilityContext availability = AvailabilityContext::alwaysAvailable();
10961097
if (!SP.P.parseSpecializeAttribute(
1097-
tok::r_square, AtLoc, Loc, Attr,
1098+
tok::r_square, AtLoc, Loc, Attr, &availability,
10981099
[&targetFunctionName](Parser &P) -> bool {
10991100
if (P.Tok.getKind() != tok::string_literal) {
11001101
P.diagnose(P.Tok, diag::expected_in_attribute_list);
@@ -1136,6 +1137,7 @@ static bool parseDeclSILOptional(bool *isTransparent,
11361137
: SILSpecializeAttr::SpecializationKind::Partial;
11371138
SpecAttr.exported = Attr->isExported();
11381139
SpecAttr.target = targetFunction;
1140+
SpecAttr.availability = availability;
11391141
SpecAttrs->emplace_back(SpecAttr);
11401142
if (!Attr->getSPIGroups().empty()) {
11411143
SpecAttr.spiGroupID = Attr->getSPIGroups()[0];
@@ -6279,7 +6281,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
62796281
GenericSignature());
62806282
FunctionState.F->addSpecializeAttr(SILSpecializeAttr::create(
62816283
FunctionState.F->getModule(), genericSig, Attr.exported,
6282-
Attr.kind, Attr.target, Attr.spiGroupID, Attr.spiModule));
6284+
Attr.kind, Attr.target, Attr.spiGroupID, Attr.spiModule, Attr.availability));
62836285
}
62846286
}
62856287

lib/SILGen/SILGen.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2209,9 +2209,12 @@ static void transferSpecializeAttributeTargets(SILGenModule &SGM, SILModule &M,
22092209
if (hasSPIGroup) {
22102210
spiGroupIdent = spiGroups[0];
22112211
}
2212+
auto availability =
2213+
AvailabilityInference::annotatedAvailableRangeForAttr(SA,
2214+
M.getSwiftModule()->getASTContext());
22122215
targetSILFunction->addSpecializeAttr(SILSpecializeAttr::create(
22132216
M, SA->getSpecializedSignature(), SA->isExported(), kind, nullptr,
2214-
spiGroupIdent, vd->getModuleContext()));
2217+
spiGroupIdent, vd->getModuleContext(), availability));
22152218
}
22162219
}
22172220
}

lib/Serialization/DeserializeSIL.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -725,9 +725,11 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
725725
IdentifierID targetFunctionID;
726726
IdentifierID spiGroupID;
727727
ModuleID spiModuleID;
728+
unsigned LIST_VER_TUPLE_PIECES(available);
728729
SILSpecializeAttrLayout::readRecord(
729730
scratch, exported, specializationKindVal, specializedSigID,
730-
targetFunctionID, spiGroupID, spiModuleID);
731+
targetFunctionID, spiGroupID, spiModuleID,
732+
LIST_VER_TUPLE_PIECES(available));
731733

732734
SILFunction *target = nullptr;
733735
if (targetFunctionID) {
@@ -745,13 +747,19 @@ SILDeserializer::readSILFunctionChecked(DeclID FID, SILFunction *existingFn,
745747
specializationKindVal ? SILSpecializeAttr::SpecializationKind::Partial
746748
: SILSpecializeAttr::SpecializationKind::Full;
747749

750+
llvm::VersionTuple available;
751+
DECODE_VER_TUPLE(available);
752+
auto availability = available.empty()
753+
? AvailabilityContext::alwaysAvailable()
754+
: AvailabilityContext(VersionRange::allGTE(available));
755+
748756
auto specializedSig = MF->getGenericSignature(specializedSigID);
749757
// Only add the specialize attributes once.
750758
if (shouldAddAtttributes) {
751759
// Read the substitution list and construct a SILSpecializeAttr.
752760
fn->addSpecializeAttr(SILSpecializeAttr::create(
753761
SILMod, specializedSig, exported != 0, specializationKind, target,
754-
spiGroup, spiModule));
762+
spiGroup, spiModule, availability));
755763
}
756764
}
757765

lib/Serialization/SILFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,8 @@ namespace sil_block {
309309
GenericSignatureIDField, // specialized signature
310310
DeclIDField, // Target SILFunction name or 0.
311311
DeclIDField, // SPIGroup or 0.
312-
DeclIDField // SPIGroup Module name id.
312+
DeclIDField, // SPIGroup Module name id.
313+
BC_AVAIL_TUPLE // Availability
313314
>;
314315

315316
// Has an optional argument list where each argument is a typed valueref.

lib/Serialization/Serialization.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3114,12 +3114,15 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
31143114
}
31153115

31163116
void noteUseOfExportedPrespecialization(const AbstractFunctionDecl *afd) {
3117+
bool hasNoted = false;
31173118
for (auto *A : afd->getAttrs().getAttributes<SpecializeAttr>()) {
31183119
auto *SA = cast<SpecializeAttr>(A);
31193120
if (!SA->isExported())
31203121
continue;
31213122
if (auto *targetFunctionDecl = SA->getTargetFunctionDecl(afd)) {
3122-
exportedPrespecializationDecls.push_back(S.addDeclRef(afd));
3123+
if (!hasNoted)
3124+
exportedPrespecializationDecls.push_back(S.addDeclRef(afd));
3125+
hasNoted = true;
31233126
}
31243127
}
31253128
}

lib/Serialization/SerializeSIL.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -509,11 +509,18 @@ void SILSerializer::writeSILFunction(const SILFunction &F, bool DeclOnly) {
509509
spiGroupID = S.addUniquedStringRef(ident.str());
510510
spiModuleDeclID = S.addModuleRef(SA->getSPIModule());
511511
}
512+
auto availability = SA->getAvailability();
513+
if (!availability.isAlwaysAvailable()) {
514+
available = availability.getOSVersion().getLowerEndpoint();
515+
}
516+
ENCODE_VER_TUPLE(available, available)
517+
512518
SILSpecializeAttrLayout::emitRecord(
513519
Out, ScratchRecord, specAttrAbbrCode, (unsigned)SA->isExported(),
514520
(unsigned)SA->getSpecializationKind(),
515521
S.addGenericSignatureRef(SA->getSpecializedSignature()),
516-
targetFunctionNameID, spiGroupID, spiModuleDeclID);
522+
targetFunctionNameID, spiGroupID, spiModuleDeclID,
523+
LIST_VER_TUPLE_PIECES(available));
517524
}
518525

519526
// Assign a unique ID to each basic block of the SILFunction.

test/SIL/Parser/available.sil

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,11 @@ sil [available 123.321.444] @version_subminor : $@convention(thin) () -> ()
2525

2626
// CHECK-LABEL: sil [weak_imported] @weak_func : $@convention(thin) () -> ()
2727
sil [weak_imported] @weak_func : $@convention(thin) () -> ()
28+
29+
public struct SomeData {}
30+
31+
// CHECK-LABEL: sil [_specialize exported: true, kind: full, available: 10.50, where T == SomeData] @specialize_availability : $@convention(thin) <T> (@in_guaranteed T) -> ()
32+
sil [_specialize exported: true, kind: full, available: 10.50, where T == SomeData] @specialize_availability : $@convention(thin) <T> (@in_guaranteed T) -> () {
33+
entry(%0 : $*T):
34+
return undef: $()
35+
}

test/SIL/Serialization/available.sil

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@
77

88
import Builtin
99

10+
public struct SomeData {}
11+
12+
// CHECK-LABEL: sil [serialized] [_specialize exported: true, kind: full, available: 10.50, where T == SomeData] @specialize_availability : $@convention(thin) <T> (@in_guaranteed T) -> ()
13+
sil [serialized] [_specialize exported: true, kind: full, available: 10.50, where T == SomeData] @specialize_availability : $@convention(thin) <T> (@in_guaranteed T) -> () {
14+
bb0(%0 : $*T):
15+
return undef : $()
16+
}
17+
1018
// CHECK-LABEL: sil [serialized] [weak_imported] @weak_func : $@convention(thin) () -> ()
1119
sil [serialized] [weak_imported] @weak_func : $@convention(thin) () -> () {
1220
bb0:

test/SILGen/Inputs/specialize_attr_module2.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import A
22

33
extension PublicThing {
44
@_specialize(exported: true, kind: full, target: doStuffWith(_:), where T == Int)
5+
@_specialize(exported: true, kind: full, target: doStuffWith(_:), availability: macOS 10.50, *; where T == Int16)
56
public func specializedoStuff2(_ t: T) {}
67
}
78

0 commit comments

Comments
 (0)