Skip to content

Commit 0d34b4d

Browse files
committed
Print @abi into module interface (suppressibly)
1 parent 0f3cf62 commit 0d34b4d

File tree

6 files changed

+111
-13
lines changed

6 files changed

+111
-13
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
@@ -437,7 +437,7 @@ EXPERIMENTAL_FEATURE(GenerateForceToMainActorThunks, false)
437437
EXPERIMENTAL_FEATURE(AddressableParameters, true)
438438

439439
/// Allow the @abi attribute.
440-
EXPERIMENTAL_FEATURE(ABIAttribute, true)
440+
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(ABIAttribute, true)
441441

442442
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
443443
#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: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ void DeclAttributes::print(ASTPrinter &Printer, const PrintOptions &Options,
785785
AttributeVector attributes;
786786
AttributeVector modifiers;
787787
bool libraryLevelAPI =
788-
D->getASTContext().LangOpts.LibraryLevel == LibraryLevel::API;
788+
D && D->getASTContext().LangOpts.LibraryLevel == LibraryLevel::API;
789789

790790
for (auto DA : llvm::reverse(FlattenedAttrs)) {
791791
// Don't skip implicit custom attributes. Custom attributes like global
@@ -1648,8 +1648,14 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
16481648
case DeclAttrKind::ABI: {
16491649
auto *attr = cast<ABIAttr>(this);
16501650
Printer << "@abi(";
1651-
if (attr->abiDecl)
1652-
attr->abiDecl->print(Printer, Options);
1651+
Decl *abiDecl = attr->abiDecl;
1652+
if (abiDecl && Options.ExplodePatternBindingDecls
1653+
&& isa<PatternBindingDecl>(abiDecl) && D && isa<VarDecl>(D))
1654+
abiDecl = cast<PatternBindingDecl>(abiDecl)
1655+
->getVarAtSimilarStructuralPosition(
1656+
const_cast<VarDecl *>(cast<VarDecl>(D)));
1657+
if (abiDecl)
1658+
abiDecl->print(Printer, Options);
16531659
Printer << ")";
16541660

16551661
break;

lib/AST/FeatureSet.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,18 @@ static bool usesFeatureAllowUnsafeAttribute(Decl *decl) {
323323
return decl->getAttrs().hasAttribute<UnsafeAttr>();
324324
}
325325

326+
static ABIAttr *getABIAttr(Decl *decl) {
327+
if (auto pbd = dyn_cast<PatternBindingDecl>(decl))
328+
for (auto i : range(pbd->getNumPatternEntries()))
329+
if (auto anchorVar = pbd->getAnchoringVarDecl(i))
330+
return getABIAttr(anchorVar);
331+
// FIXME: EnumCaseDecl/EnumElementDecl
332+
333+
return decl->getAttrs().getAttribute<ABIAttr>();
334+
}
335+
326336
static bool usesFeatureABIAttribute(Decl *decl) {
327-
auto abiAttr = decl->getAttrs().getAttribute<ABIAttr>();
328-
return abiAttr && !abiAttr->isInverse();
337+
return getABIAttr(decl) != nullptr;
329338
}
330339

331340
UNINTERESTING_FEATURE(WarnUnsafe)
@@ -430,26 +439,38 @@ static bool allowFeatureSuppression(StringRef featureName, Decl *decl) {
430439
/// Go through all the features used by the given declaration and
431440
/// either add or remove them to this set.
432441
void FeatureSet::collectFeaturesUsed(Decl *decl, InsertOrRemove operation) {
442+
// Count feature usage in an ABI decl as feature usage by the API, not itself,
443+
// since we can't use `#if` inside an @abi attribute.
444+
Decl *abiDecl = nullptr;
445+
if (auto abiAttr = getABIAttr(decl)) {
446+
abiDecl = abiAttr->abiDecl;
447+
}
448+
449+
#define CHECK(Function) (Function(decl) || (abiDecl && Function(abiDecl)))
450+
#define CHECK_ARG(Function, Arg) (Function(Arg, decl) || (abiDecl && Function(Arg, abiDecl)))
451+
433452
// Go through each of the features, checking whether the
434453
// declaration uses that feature.
435454
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
436-
if (usesFeature##FeatureName(decl)) \
455+
if (CHECK(usesFeature##FeatureName)) \
437456
collectRequiredFeature(Feature::FeatureName, operation);
438457
#define SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
439-
if (usesFeature##FeatureName(decl)) { \
440-
if (disallowFeatureSuppression(#FeatureName, decl)) \
458+
if (CHECK(usesFeature##FeatureName)) { \
459+
if (CHECK_ARG(disallowFeatureSuppression, #FeatureName)) \
441460
collectRequiredFeature(Feature::FeatureName, operation); \
442461
else \
443462
collectSuppressibleFeature(Feature::FeatureName, operation); \
444463
}
445464
#define CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
446-
if (usesFeature##FeatureName(decl)) { \
447-
if (allowFeatureSuppression(#FeatureName, decl)) \
465+
if (CHECK(usesFeature##FeatureName)) { \
466+
if (CHECK_ARG(allowFeatureSuppression, #FeatureName)) \
448467
collectSuppressibleFeature(Feature::FeatureName, operation); \
449468
else \
450469
collectRequiredFeature(Feature::FeatureName, operation); \
451470
}
452471
#include "swift/Basic/Features.def"
472+
#undef CHECK
473+
#undef CHECK_ARG
453474
}
454475

455476
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)