Skip to content

Commit 3bc5d03

Browse files
committed
Print @abi into module interface (suppressibly)
1 parent fc81845 commit 3bc5d03

File tree

6 files changed

+112
-12
lines changed

6 files changed

+112
-12
lines changed

include/swift/AST/PrintOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,10 @@ struct PrintOptions {
237237
/// Use the original module name to qualify a symbol.
238238
bool UseOriginallyDefinedInModuleNames = false;
239239

240+
/// Add a `@_silgen_name` attribute to each function that
241+
/// is compatible with one that specifies its mangled name.
242+
bool PrintSyntheticSILGenName = false;
243+
240244
/// Print Swift.Array and Swift.Optional with sugared syntax
241245
/// ([] and ?), even if there are no sugar type nodes.
242246
bool SynthesizeSugarOnTypes = false;

include/swift/Basic/Features.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ EXPERIMENTAL_FEATURE(CoroutineAccessorsAllocateInCallee, false)
431431
EXPERIMENTAL_FEATURE(GenerateForceToMainActorThunks, false)
432432

433433
/// Allow the @abi attribute.
434-
EXPERIMENTAL_FEATURE(ABIAttribute, true)
434+
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(ABIAttribute, true)
435435

436436
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
437437
#undef EXPERIMENTAL_FEATURE

lib/AST/ASTPrinter.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,18 @@ static bool hasLessAccessibleSetter(const AbstractStorageDecl *ASD) {
12301230
return ASD->getSetterFormalAccess() < ASD->getFormalAccess();
12311231
}
12321232

1233+
bool canPrintSyntheticSILGenName(const Decl *D) {
1234+
ASSERT(!D->getAttrs().hasAttribute<SILGenNameAttr>());
1235+
1236+
// Only print on functions, and only those functions with no barriers to use.
1237+
if (auto FD = dyn_cast<AbstractFunctionDecl>(D); !FD
1238+
|| FD->getAttrs().hasAttribute<BackDeployedAttr>()
1239+
|| FD->getOpaqueResultTypeDecl())
1240+
return false;
1241+
1242+
return true;
1243+
}
1244+
12331245
void PrintAST::printAttributes(const Decl *D) {
12341246
if (Options.SkipAttributes)
12351247
return;
@@ -1247,6 +1259,27 @@ void PrintAST::printAttributes(const Decl *D) {
12471259
// for each decl They cannot be shared across different decls.
12481260
assert(Options.ExcludeCustomAttrList.empty());
12491261

1262+
if (Options.PrintSyntheticSILGenName
1263+
&& !D->getAttrs().hasAttribute<SILGenNameAttr>()) {
1264+
if (canPrintSyntheticSILGenName(D)) {
1265+
auto mangledName = Mangle::ASTMangler(D->getASTContext())
1266+
.mangleAnyDecl(cast<ValueDecl>(D), /*prefix=*/true,
1267+
/*respectOriginallyDefinedIn=*/true);
1268+
Printer.printAttrName("@_silgen_name");
1269+
Printer << "(";
1270+
Printer.printEscapedStringLiteral(mangledName);
1271+
Printer << ")\n";
1272+
}
1273+
else {
1274+
Printer.printAttrName("@available");
1275+
Printer << "(*, unavailable, message: ";
1276+
Printer.printEscapedStringLiteral(
1277+
"this compiler cannot match the ABI specified by the @abi attribute");
1278+
Printer << ")\n";
1279+
Options.ExcludeAttrList.push_back(DeclAttrKind::Available);
1280+
}
1281+
}
1282+
12501283
if (Options.PrintImplicitAttrs) {
12511284

12521285
// Don't print a redundant 'final' if we are printing a 'static' decl.
@@ -3139,6 +3172,16 @@ suppressingFeatureCoroutineAccessors(PrintOptions &options,
31393172
action();
31403173
}
31413174

3175+
static void
3176+
suppressingFeatureABIAttribute(PrintOptions &options,
3177+
llvm::function_ref<void()> action) {
3178+
llvm::SaveAndRestore<bool> scope(options.PrintSyntheticSILGenName, true);
3179+
unsigned originalExcludeAttrCount = options.ExcludeAttrList.size();
3180+
options.ExcludeAttrList.push_back(DeclAttrKind::ABI);
3181+
action();
3182+
options.ExcludeAttrList.resize(originalExcludeAttrCount);
3183+
}
3184+
31423185
/// Suppress the printing of a particular feature.
31433186
static void suppressingFeature(PrintOptions &options, Feature feature,
31443187
llvm::function_ref<void()> action) {
@@ -3910,6 +3953,8 @@ void PrintAST::printOneParameter(const ParamDecl *param,
39103953
void PrintAST::printParameterList(ParameterList *PL,
39113954
ArrayRef<AnyFunctionType::Param> params,
39123955
bool isAPINameByDefault) {
3956+
llvm::SaveAndRestore<bool> scope(Options.PrintSyntheticSILGenName, false);
3957+
39133958
Printer.printStructurePre(PrintStructureKind::FunctionParameterList);
39143959
SWIFT_DEFER {
39153960
Printer.printStructurePost(PrintStructureKind::FunctionParameterList);

lib/AST/Attr.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -775,7 +775,7 @@ void DeclAttributes::print(ASTPrinter &Printer, const PrintOptions &Options,
775775
AttributeVector attributes;
776776
AttributeVector modifiers;
777777
bool libraryLevelAPI =
778-
D->getASTContext().LangOpts.LibraryLevel == LibraryLevel::API;
778+
D && D->getASTContext().LangOpts.LibraryLevel == LibraryLevel::API;
779779

780780
for (auto DA : llvm::reverse(FlattenedAttrs)) {
781781
// Don't skip implicit custom attributes. Custom attributes like global
@@ -1589,7 +1589,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
15891589
auto *attr = cast<ABIAttr>(this);
15901590
Printer << "@abi(";
15911591
ASSERT(!attr->isInverse() && "should be skipped above");
1592-
if (attr->abiDecl)
1592+
Decl *abiDecl = attr->abiDecl;
1593+
if (abiDecl && Options.ExplodePatternBindingDecls
1594+
&& isa<PatternBindingDecl>(abiDecl) && D && isa<VarDecl>(D))
1595+
abiDecl = cast<PatternBindingDecl>(abiDecl)
1596+
->getVarAtSimilarStructuralPosition(
1597+
const_cast<VarDecl *>(cast<VarDecl>(D)));
1598+
if (abiDecl)
15931599
attr->abiDecl->print(Printer, Options);
15941600
Printer << ")";
15951601

lib/AST/FeatureSet.cpp

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -305,9 +305,18 @@ static bool usesFeatureAllowUnsafeAttribute(Decl *decl) {
305305
return decl->getAttrs().hasAttribute<UnsafeAttr>();
306306
}
307307

308+
static ABIAttr *getABIAttr(Decl *decl) {
309+
if (auto pbd = dyn_cast<PatternBindingDecl>(decl))
310+
for (auto i : range(pbd->getNumPatternEntries()))
311+
if (auto anchorVar = pbd->getAnchoringVarDecl(i))
312+
return getABIAttr(anchorVar);
313+
// FIXME: EnumCaseDecl/EnumElementDecl
314+
315+
return decl->getAttrs().getAttribute<ABIAttr>();
316+
}
317+
308318
static bool usesFeatureABIAttribute(Decl *decl) {
309-
auto abiAttr = decl->getAttrs().getAttribute<ABIAttr>();
310-
return abiAttr && !abiAttr->isInverse();
319+
return getABIAttr(decl) != nullptr;
311320
}
312321

313322
UNINTERESTING_FEATURE(WarnUnsafe)
@@ -411,26 +420,40 @@ static bool allowFeatureSuppression(StringRef featureName, Decl *decl) {
411420
/// Go through all the features used by the given declaration and
412421
/// either add or remove them to this set.
413422
void FeatureSet::collectFeaturesUsed(Decl *decl, InsertOrRemove operation) {
423+
// Count feature usage in an ABI decl as feature usage by the API, not itself,
424+
// since we can't use `#if` inside an @abi attribute.
425+
Decl *abiDecl = nullptr;
426+
if (auto abiAttr = getABIAttr(decl)) {
427+
if (abiAttr->isInverse())
428+
return;
429+
abiDecl = abiAttr->abiDecl;
430+
}
431+
432+
#define CHECK(Function) (Function(decl) || (abiDecl && Function(abiDecl)))
433+
#define CHECK_ARG(Function, Arg) (Function(Arg, decl) || (abiDecl && Function(Arg, abiDecl)))
434+
414435
// Go through each of the features, checking whether the
415436
// declaration uses that feature.
416437
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
417-
if (usesFeature##FeatureName(decl)) \
438+
if (CHECK(usesFeature##FeatureName)) \
418439
collectRequiredFeature(Feature::FeatureName, operation);
419440
#define SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
420-
if (usesFeature##FeatureName(decl)) { \
421-
if (disallowFeatureSuppression(#FeatureName, decl)) \
441+
if (CHECK(usesFeature##FeatureName)) { \
442+
if (CHECK_ARG(disallowFeatureSuppression, #FeatureName)) \
422443
collectRequiredFeature(Feature::FeatureName, operation); \
423444
else \
424445
collectSuppressibleFeature(Feature::FeatureName, operation); \
425446
}
426447
#define CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
427-
if (usesFeature##FeatureName(decl)) { \
428-
if (allowFeatureSuppression(#FeatureName, decl)) \
448+
if (CHECK(usesFeature##FeatureName)) { \
449+
if (CHECK_ARG(allowFeatureSuppression, #FeatureName)) \
429450
collectSuppressibleFeature(Feature::FeatureName, operation); \
430451
else \
431452
collectRequiredFeature(Feature::FeatureName, operation); \
432453
}
433454
#include "swift/Basic/Features.def"
455+
#undef CHECK
456+
#undef CHECK_ARG
434457
}
435458

436459
FeatureSet swift::getUniqueFeaturesUsed(Decl *decl) {

test/ModuleInterface/attrs.swift

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name attrs
1+
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %s -module-name attrs -enable-experimental-feature ABIAttribute
22
// RUN: %target-swift-typecheck-module-from-interface(%t.swiftinterface) -module-name attrs
3-
// RUN: %FileCheck %s < %t.swiftinterface
3+
// RUN: %FileCheck %s --input-file %t.swiftinterface
4+
5+
// REQUIRES: swift_feature_ABIAttribute
46

57
// CHECK: @_transparent public func glass() -> Swift.Int { return 0 }{{$}}
68
@_transparent public func glass() -> Int { return 0 }
@@ -27,3 +29,23 @@ public func someGenericFunction<T>(_ t: T) -> Int { return 0 }
2729
internal func __specialize_someGenericFunction<T>(_ t: T) -> Int {
2830
fatalError("don't call")
2931
}
32+
33+
@abi(public func __abi__abiAttrOnFunction(param: Int))
34+
public func abiAttrOnFunction(param: Int) {}
35+
// CHECK: #if {{.*}} $ABIAttribute
36+
// CHECK: @abi(public func __abi__abiAttrOnFunction(param: Swift.Int))
37+
// CHECK: public func abiAttrOnFunction(param: Swift.Int)
38+
// CHECK: #else
39+
// CHECK: @_silgen_name("$s5attrs07__abi__B14AttrOnFunction5paramySi_tF")
40+
// CHECK: public func abiAttrOnFunction(param: Swift.Int)
41+
// CHECK: #endif
42+
43+
@abi(public let __abi__abiAttrOnVar: Int)
44+
public var abiAttrOnVar: Int = 42
45+
// CHECK: #if {{.*}} $ABIAttribute
46+
// CHECK: @abi(public var __abi__abiAttrOnVar: Swift.Int)
47+
// CHECK: public var abiAttrOnVar: Swift.Int
48+
// CHECK: #else
49+
// CHECK: @available(*, unavailable, message: "this compiler cannot match the ABI specified by the @abi attribute")
50+
// CHECK: public var abiAttrOnVar: Swift.Int
51+
// CHECK: #endif

0 commit comments

Comments
 (0)