Skip to content

Commit 4c63dd8

Browse files
committed
[ASTGen] Lower @abi in ASTGen
1 parent 62254a4 commit 4c63dd8

File tree

10 files changed

+263
-9
lines changed

10 files changed

+263
-9
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,11 +567,34 @@ SWIFT_NAME("BridgedDeclAttributes.add(self:_:)")
567567
void BridgedDeclAttributes_add(BridgedDeclAttributes *_Nonnull attrs,
568568
BridgedDeclAttribute add);
569569

570+
/// Retrieve the attribute from \p cAttrs that comes after \p cPriorAttr .
571+
/// If \c cPriorAttr is null, retrieves the first attribute. If there are no
572+
/// more attributes, returns null.
573+
SWIFT_NAME("BridgedDeclAttributes.attr(self:after:)")
574+
BridgedNullableDeclAttribute BridgedDeclAttributes_getAttrAfter(
575+
BridgedDeclAttributes cAttrs, BridgedNullableDeclAttribute cPriorAttr);
576+
570577
SWIFT_NAME("BridgedDeclAttribute.createSimple(_:kind:atLoc:nameLoc:)")
571578
BridgedDeclAttribute BridgedDeclAttribute_createSimple(
572579
BridgedASTContext cContext, BridgedDeclAttrKind cKind,
573580
BridgedSourceLoc cAtLoc, BridgedSourceLoc cNameLoc);
574581

582+
SWIFT_NAME("getter:BridgedDeclAttribute.asABIAttr(self:)")
583+
BridgedNullableABIAttr BridgedDeclAttribute_asABIAttr(
584+
BridgedDeclAttribute cAttr);
585+
586+
SWIFT_NAME("BridgedABIAttr.createParsed(_:atLoc:range:abiDecl:)")
587+
BridgedABIAttr BridgedABIAttr_createParsed(
588+
BridgedASTContext cContext, BridgedSourceLoc atLoc,
589+
BridgedSourceRange range, BridgedNullableDecl abiDecl);
590+
591+
SWIFT_NAME("BridgedABIAttr.createImplicitInverse(_:)")
592+
BridgedABIAttr BridgedABIAttr_createImplicitInverse(
593+
BridgedASTContext cContext);
594+
595+
SWIFT_NAME("BridgedABIAttr.connectToInverse(self:attachedTo:)")
596+
void BridgedABIAttr_connectToInverse(BridgedABIAttr cAttr, BridgedDecl cOwner);
597+
575598
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedAccessLevel {
576599
BridgedAccessLevelPrivate,
577600
BridgedAccessLevelFilePrivate,
@@ -913,6 +936,10 @@ BridgedDeclAttributes BridgedDecl_getAttrs(BridgedDecl decl);
913936
SWIFT_NAME("setter:BridgedDecl.attrs(self:newValue:)")
914937
void BridgedDecl_setAttrs(BridgedDecl decl, BridgedDeclAttributes attrs);
915938

939+
SWIFT_NAME("getter:BridgedDecl.asPatternBindingDecl(self:)")
940+
BridgedNullablePatternBindingDecl BridgedDecl_getAsPatternBindingDecl(
941+
BridgedDecl decl);
942+
916943
enum ENUM_EXTENSIBILITY_ATTR(closed) BridgedStaticSpelling {
917944
BridgedStaticSpellingNone,
918945
BridgedStaticSpellingStatic,
@@ -948,6 +975,14 @@ BridgedPatternBindingDecl BridgedPatternBindingDecl_createParsed(
948975
BridgedSourceLoc cBindingKeywordLoc, BridgedArrayRef cBindingEntries, BridgedDeclAttributes cAttrs,
949976
bool isStatic, bool isLet);
950977

978+
SWIFT_NAME("getter:BridgedPatternBindingDecl.patternCount(self:)")
979+
SwiftInt BridgedPatternBindingDecl_getNumPatternEntries(
980+
BridgedPatternBindingDecl cPBD);
981+
982+
SWIFT_NAME("BridgedPatternBindingDecl.pattern(self:at:)")
983+
BridgedPattern BridgedPatternBindingDecl_getPattern(
984+
BridgedPatternBindingDecl cPBD, SwiftInt i);
985+
951986
SWIFT_NAME("BridgedParamDecl.createParsed(_:declContext:specifierLoc:argName:"
952987
"argNameLoc:paramName:paramNameLoc:type:defaultValue:)")
953988
BridgedParamDecl BridgedParamDecl_createParsed(
@@ -2105,6 +2140,21 @@ void BridgedTypeRepr_dump(BridgedTypeRepr type);
21052140
SWIFT_NAME("getter:BridgedPattern.singleVar(self:)")
21062141
BridgedNullableVarDecl BridgedPattern_getSingleVar(BridgedPattern cPattern);
21072142

2143+
/// Iterates over the pattern, collecting and returning all of the BridgedVarDecls
2144+
/// referenced by its subpatterns.
2145+
///
2146+
/// The exact semantics of this are as follows:
2147+
///
2148+
/// \li This method always returns the current count of BridgedVarDecls in the
2149+
/// pattern.
2150+
/// \li If \p capacity is greater than or equal to the current count \em and
2151+
/// \p varDeclArrayOut is non-null, this method also writes the
2152+
/// BridgedVarDecls into the buffer starting at \p varDeclArrayOut .
2153+
SWIFT_NAME("BridgedPattern.unsafeFetchVarDecls(self:into:capacity:)")
2154+
SwiftInt BridgedPattern_unsafeFetchVarDecls(
2155+
BridgedPattern cPattern, BridgedVarDecl * _Nullable varDeclArrayOut,
2156+
SwiftInt capacity);
2157+
21082158
SWIFT_NAME("BridgedAnyPattern.createParsed(_:loc:)")
21092159
BridgedAnyPattern BridgedAnyPattern_createParsed(BridgedASTContext cContext,
21102160
BridgedSourceLoc cLoc);

include/swift/AST/ASTBridgingWrappers.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@
6262

6363
#ifndef DECL_ATTR
6464
#define SIMPLE_DECL_ATTR(...)
65-
#define DECL_ATTR(_, Id, ...) AST_BRIDGING_WRAPPER_NONNULL(Id##Attr)
65+
#define DECL_ATTR(_, Id, ...) AST_BRIDGING_WRAPPER_NULLABLE(Id##Attr)
6666
#endif
6767
#include "swift/AST/DeclAttr.def"
6868

6969
// Some of the base classes need to be nullable to allow them to be used as
7070
// optional parameters.
71-
AST_BRIDGING_WRAPPER_NONNULL(Decl)
71+
AST_BRIDGING_WRAPPER_NULLABLE(Decl)
7272
AST_BRIDGING_WRAPPER_NONNULL(DeclContext)
7373
AST_BRIDGING_WRAPPER_NONNULL(SourceFile)
7474
AST_BRIDGING_WRAPPER_NULLABLE(Stmt)

lib/AST/Bridging/DeclAttributeBridging.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,42 @@ static std::optional<AccessLevel> unbridge(BridgedAccessLevel level) {
9393
llvm_unreachable("unhandled BridgedAccessLevel");
9494
}
9595

96+
BridgedNullableDeclAttribute BridgedDeclAttributes_getAttrAfter(
97+
BridgedDeclAttributes cAttrs, BridgedNullableDeclAttribute cPriorAttr) {
98+
auto attrs = cAttrs.unbridged();
99+
auto priorAttr = cPriorAttr.unbridged();
100+
101+
auto i = priorAttr ? std::next(DeclAttributes::iterator(priorAttr))
102+
: attrs.begin();
103+
return *i;
104+
}
105+
106+
BridgedNullableABIAttr BridgedDeclAttribute_asABIAttr(
107+
BridgedDeclAttribute cAttr) {
108+
return dyn_cast<ABIAttr>(cAttr.unbridged());
109+
}
110+
111+
BridgedABIAttr BridgedABIAttr_createParsed(BridgedASTContext cContext,
112+
BridgedSourceLoc atLoc,
113+
BridgedSourceRange range,
114+
BridgedNullableDecl abiDecl) {
115+
return new (cContext.unbridged()) ABIAttr(abiDecl.unbridged(),
116+
atLoc.unbridged(),
117+
range.unbridged(),
118+
/*isInverse=*/false,
119+
/*isImplicit=*/false);
120+
}
121+
122+
BridgedABIAttr BridgedABIAttr_createImplicitInverse(BridgedASTContext cContext){
123+
return new (cContext.unbridged()) ABIAttr(nullptr,
124+
/*isInverse=*/true,
125+
/*isImplicit=*/true);
126+
}
127+
128+
void BridgedABIAttr_connectToInverse(BridgedABIAttr cAttr, BridgedDecl cOwner) {
129+
return cAttr.unbridged()->connectToInverse(cOwner.unbridged());
130+
}
131+
96132
BridgedAccessControlAttr
97133
BridgedAccessControlAttr_createParsed(BridgedASTContext cContext,
98134
BridgedSourceRange cRange,

lib/AST/Bridging/DeclBridging.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,13 @@ void BridgedDecl_setAttrs(BridgedDecl decl, BridgedDeclAttributes attrs) {
123123
decl.unbridged()->getAttrs() = attrs.unbridged();
124124
}
125125

126+
// FIXME: We should do this systematically for downcasting BridgedDecl to all
127+
// subclasses.
128+
BridgedNullablePatternBindingDecl BridgedDecl_getAsPatternBindingDecl(
129+
BridgedDecl decl) {
130+
return dyn_cast<PatternBindingDecl>(decl.unbridged());
131+
}
132+
126133
BridgedAccessorDecl BridgedAccessorDecl_createParsed(
127134
BridgedASTContext cContext, BridgedDeclContext cDeclContext,
128135
BridgedAccessorKind cKind, BridgedAbstractStorageDecl cStorage,
@@ -167,6 +174,17 @@ BridgedPatternBindingDecl BridgedPatternBindingDecl_createParsed(
167174
cBindingKeywordLoc.unbridged(), entries, declContext);
168175
}
169176

177+
SwiftInt BridgedPatternBindingDecl_getNumPatternEntries(
178+
BridgedPatternBindingDecl cPBD) {
179+
return cPBD.unbridged()->getNumPatternEntries();
180+
}
181+
182+
BridgedPattern BridgedPatternBindingDecl_getPattern(
183+
BridgedPatternBindingDecl cPBD, SwiftInt i) {
184+
ASSERT(i >= 0 && i < cPBD.unbridged()->getNumPatternEntries());
185+
return cPBD.unbridged()->getPattern(i);
186+
}
187+
170188
BridgedParamDecl BridgedParamDecl_createParsed(
171189
BridgedASTContext cContext, BridgedDeclContext cDeclContext,
172190
BridgedSourceLoc cSpecifierLoc, BridgedIdentifier cArgName,

lib/AST/Bridging/PatternBridging.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@ BridgedNullableVarDecl BridgedPattern_getSingleVar(BridgedPattern cPattern) {
3737
return cPattern.unbridged()->getSingleVar();
3838
}
3939

40+
SwiftInt BridgedPattern_unsafeFetchVarDecls(BridgedPattern cPattern,
41+
BridgedVarDecl *varDeclArrayOut,
42+
SwiftInt capacity) {
43+
SmallVector<VarDecl *, 32> vars;
44+
cPattern.unbridged()->collectVariables(vars);
45+
46+
if (varDeclArrayOut && vars.size() <= (size_t)capacity) {
47+
for (auto i : indices(vars)) {
48+
varDeclArrayOut[i] = vars[i];
49+
}
50+
}
51+
52+
return vars.size();
53+
}
54+
4055
BridgedAnyPattern BridgedAnyPattern_createParsed(BridgedASTContext cContext,
4156
BridgedSourceLoc cLoc) {
4257
return new (cContext.unbridged()) AnyPattern(cLoc.unbridged());

lib/ASTGen/Sources/ASTGen/Bridge.swift

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ extension BridgedNullable {
2727

2828
extension BridgedSourceLoc: /*@retroactive*/ swiftASTGen.BridgedNullable {}
2929
extension BridgedIdentifier: /*@retroactive*/ swiftASTGen.BridgedNullable {}
30+
extension BridgedNullableDeclAttribute: /*@retroactive*/ swiftASTGen.BridgedNullable {}
31+
extension BridgedNullableDecl: /*@retroactive*/ swiftASTGen.BridgedNullable {}
3032
extension BridgedNullableExpr: /*@retroactive*/ swiftASTGen.BridgedNullable {}
3133
extension BridgedNullableStmt: /*@retroactive*/ swiftASTGen.BridgedNullable {}
3234
extension BridgedNullableTypeRepr: /*@retroactive*/ swiftASTGen.BridgedNullable {}
@@ -38,6 +40,7 @@ extension BridgedNullablePatternBindingInitializer: /*@retroactive*/ swiftASTGen
3840
extension BridgedNullableArgumentList: /*@retroactive*/ swiftASTGen.BridgedNullable {}
3941
extension BridgedNullablePatternBindingDecl: /*@retroactive*/ swiftASTGen.BridgedNullable {}
4042
extension BridgedNullableVarDecl: /*@retroactive*/ swiftASTGen.BridgedNullable {}
43+
extension BridgedNullableABIAttr: /*@retroactive*/ swiftASTGen.BridgedNullable {}
4144

4245
extension BridgedIdentifier: /*@retroactive*/ Swift.Equatable {
4346
public static func == (lhs: Self, rhs: Self) -> Bool {
@@ -71,6 +74,12 @@ extension BridgedHasNullable {
7174
extension BridgedStmt: BridgedHasNullable {
7275
typealias Nullable = BridgedNullableStmt
7376
}
77+
extension BridgedDeclAttribute: BridgedHasNullable {
78+
typealias Nullable = BridgedNullableDeclAttribute
79+
}
80+
extension BridgedDecl: BridgedHasNullable {
81+
typealias Nullable = BridgedNullableDecl
82+
}
7483
extension BridgedExpr: BridgedHasNullable {
7584
typealias Nullable = BridgedNullableExpr
7685
}
@@ -101,6 +110,9 @@ extension BridgedPatternBindingDecl: BridgedHasNullable {
101110
extension BridgedVarDecl: BridgedHasNullable {
102111
typealias Nullable = BridgedNullableVarDecl
103112
}
113+
extension BridgedABIAttr: BridgedHasNullable {
114+
typealias Nullable = BridgedNullableABIAttr
115+
}
104116

105117
public extension BridgedSourceLoc {
106118
/// Form a source location at the given absolute position in `buffer`.
@@ -253,6 +265,56 @@ extension BridgedSourceRange {
253265
}
254266
}
255267

268+
extension BridgedPatternBindingDecl {
269+
var patterns: [BridgedPattern] {
270+
return (0 ..< patternCount).map(pattern(at:))
271+
}
272+
}
273+
274+
extension BridgedPattern {
275+
private enum FetchVarDeclsError: Error {
276+
case insufficientCapacity(Int)
277+
}
278+
279+
private func fetchVarDecls(capacity: Int) throws -> [BridgedVarDecl] {
280+
return try Array(unsafeUninitializedCapacity: capacity) { buffer, initializedCount in
281+
let fullCount = self.unsafeFetchVarDecls(
282+
into: buffer.baseAddress,
283+
capacity: buffer.count
284+
)
285+
286+
guard fullCount <= buffer.count else {
287+
throw FetchVarDeclsError.insufficientCapacity(fullCount)
288+
}
289+
290+
// `unsafeFetchVarDecls` writes nothing if `fullCount` > `capacity`, so
291+
// it's correct to put this after the `throw`.
292+
initializedCount = fullCount
293+
}
294+
}
295+
296+
var varDecls: [BridgedVarDecl] {
297+
do {
298+
return try fetchVarDecls(capacity: 8) // "probably big enough" guess
299+
}
300+
catch FetchVarDeclsError.insufficientCapacity(let neededCapacity) {
301+
return try! fetchVarDecls(capacity: neededCapacity)
302+
}
303+
catch {
304+
fatalError("Unknown error \(error)")
305+
}
306+
}
307+
}
308+
309+
extension BridgedDeclAttributes {
310+
var attrs: UnfoldSequence<BridgedDeclAttribute, BridgedNullableDeclAttribute> {
311+
return sequence(state: nil) { prior in
312+
prior = self.attr(after: prior)
313+
return BridgedDeclAttribute(prior)
314+
}
315+
}
316+
}
317+
256318
/// Helper collection type that lazily concatenates two collections.
257319
struct ConcatCollection<C1: Collection, C2: Collection> where C1.Element == C2.Element {
258320
let c1: C1

lib/ASTGen/Sources/ASTGen/DeclAttrs.swift

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@ import SwiftIfConfig
1717

1818
@_spi(ExperimentalLanguageFeatures) @_spi(RawSyntax) import SwiftSyntax
1919

20+
/// Calls `visitor` on each declaration that an `@abi` attribute `decl` ought to apply to.
21+
/// This is usually just `decl` itself, but for pattern binding decls, it's all of the
22+
/// variables bound to it.
23+
func visitABIDecls(for decl: BridgedDecl, visitor: (BridgedDecl) -> Void) {
24+
if let pbd = BridgedPatternBindingDecl(decl.asPatternBindingDecl) {
25+
for pattern in pbd.patterns {
26+
for varDecl in pattern.varDecls {
27+
visitABIDecls(for: varDecl.asDecl, visitor: visitor)
28+
}
29+
}
30+
return
31+
}
32+
33+
visitor(decl)
34+
}
35+
2036
extension ASTGenVisitor {
2137
struct DeclAttributesResult {
2238
var attributes: BridgedDeclAttributes
@@ -26,6 +42,11 @@ extension ASTGenVisitor {
2642

2743
func attach(to decl: BridgedDecl) {
2844
decl.attrs = attributes
45+
if let abiAttr = attributes.attrs.lazy.map(\.asABIAttr).compactMap(BridgedABIAttr.init).first {
46+
visitABIDecls(for: decl) { declToConnect in
47+
abiAttr.connectToInverse(attachedTo: declToConnect)
48+
}
49+
}
2950
}
3051
}
3152

@@ -330,8 +351,55 @@ extension ASTGenVisitor {
330351
/// @abi(func fn())
331352
/// ```
332353
func generateABIAttr(attribute node: AttributeSyntax) -> BridgedABIAttr? {
333-
#warning("TODO: implement generateABIAttr")
334-
fatalError("TODO: implement generateABIAttr")
354+
guard
355+
let arg = node.arguments?.as(ABIAttributeArgumentsSyntax.self)
356+
else {
357+
// TODO: diagnose
358+
return nil
359+
}
360+
361+
let abiDecl: BridgedDecl?
362+
switch arg.provider {
363+
case .associatedType(let assocTyDecl):
364+
abiDecl = self.generate(associatedTypeDecl: assocTyDecl)?.asDecl
365+
case .deinitializer(let deinitDecl):
366+
abiDecl = self.generate(deinitializerDecl: deinitDecl).asDecl
367+
case .enumCase(let caseDecl):
368+
abiDecl = self.generate(enumCaseDecl: caseDecl).asDecl
369+
case .function(let funcDecl):
370+
abiDecl = self.generate(functionDecl: funcDecl)?.asDecl
371+
case .initializer(let initDecl):
372+
abiDecl = self.generate(initializerDecl: initDecl).asDecl
373+
case .`subscript`(let subscriptDecl):
374+
abiDecl = self.generate(subscriptDecl: subscriptDecl).asDecl
375+
case .typeAlias(let typealiasDecl):
376+
abiDecl = self.generate(typeAliasDecl: typealiasDecl)?.asDecl
377+
case .variable(let varDecl):
378+
abiDecl = self.generate(variableDecl: varDecl).asDecl
379+
case .missing(_):
380+
// This error condition will have been diagnosed in SwiftSyntax.
381+
abiDecl = nil
382+
}
383+
384+
// Attach empty inverse @abi attributes to each (relevant) decl
385+
if let abiDecl {
386+
// TODO: Diagnose if `abiDecl` has a body/initial value/etc.--the C++ parser considers it syntactically invalid
387+
// but SwiftSyntax does not.
388+
389+
visitABIDecls(for: abiDecl) { decl in
390+
let attr = BridgedABIAttr.createImplicitInverse(self.ctx)
391+
var attrs = decl.attrs
392+
attrs.add(attr.asDeclAttribute)
393+
decl.attrs = attrs
394+
}
395+
}
396+
397+
return .createParsed(
398+
self.ctx,
399+
atLoc: self.generateSourceLoc(node.atSign),
400+
range: self.generateAttrSourceRange(node),
401+
abiDecl: abiDecl.asNullable
402+
)
335403
}
336404

337405
/// E.g.:

lib/ASTGen/Sources/ASTGen/SourceFile.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ extension Parser.ExperimentalFeatures {
7676
mapFeature(.TrailingComma, to: .trailingComma)
7777
mapFeature(.CoroutineAccessors, to: .coroutineAccessors)
7878
mapFeature(.ValueGenerics, to: .valueGenerics)
79+
mapFeature(.ABIAttribute, to: .abiAttribute)
7980
}
8081
}
8182

0 commit comments

Comments
 (0)