Skip to content

Commit d02c414

Browse files
committed
Print @abi into module interface (suppressibly)
1 parent 1ff6967 commit d02c414

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
@@ -433,7 +433,7 @@ EXPERIMENTAL_FEATURE(GenerateForceToMainActorThunks, false)
433433
EXPERIMENTAL_FEATURE(AddressableParameters, true)
434434

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

438438
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
439439
#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
@@ -786,7 +786,7 @@ void DeclAttributes::print(ASTPrinter &Printer, const PrintOptions &Options,
786786
AttributeVector attributes;
787787
AttributeVector modifiers;
788788
bool libraryLevelAPI =
789-
D->getASTContext().LangOpts.LibraryLevel == LibraryLevel::API;
789+
D && D->getASTContext().LangOpts.LibraryLevel == LibraryLevel::API;
790790

791791
for (auto DA : llvm::reverse(FlattenedAttrs)) {
792792
// Don't skip implicit custom attributes. Custom attributes like global
@@ -1600,7 +1600,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
16001600
auto *attr = cast<ABIAttr>(this);
16011601
Printer << "@abi(";
16021602
ASSERT(!attr->isInverse() && "should be skipped above");
1603-
if (attr->abiDecl)
1603+
Decl *abiDecl = attr->abiDecl;
1604+
if (abiDecl && Options.ExplodePatternBindingDecls
1605+
&& isa<PatternBindingDecl>(abiDecl) && D && isa<VarDecl>(D))
1606+
abiDecl = cast<PatternBindingDecl>(abiDecl)
1607+
->getVarAtSimilarStructuralPosition(
1608+
const_cast<VarDecl *>(cast<VarDecl>(D)));
1609+
if (abiDecl)
16041610
attr->abiDecl->print(Printer, Options);
16051611
Printer << ")";
16061612

lib/AST/FeatureSet.cpp

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

322+
static ABIAttr *getABIAttr(Decl *decl) {
323+
if (auto pbd = dyn_cast<PatternBindingDecl>(decl))
324+
for (auto i : range(pbd->getNumPatternEntries()))
325+
if (auto anchorVar = pbd->getAnchoringVarDecl(i))
326+
return getABIAttr(anchorVar);
327+
// FIXME: EnumCaseDecl/EnumElementDecl
328+
329+
return decl->getAttrs().getAttribute<ABIAttr>();
330+
}
331+
322332
static bool usesFeatureABIAttribute(Decl *decl) {
323-
auto abiAttr = decl->getAttrs().getAttribute<ABIAttr>();
324-
return abiAttr && !abiAttr->isInverse();
333+
return getABIAttr(decl) != nullptr;
325334
}
326335

327336
UNINTERESTING_FEATURE(WarnUnsafe)
@@ -425,26 +434,40 @@ static bool allowFeatureSuppression(StringRef featureName, Decl *decl) {
425434
/// Go through all the features used by the given declaration and
426435
/// either add or remove them to this set.
427436
void FeatureSet::collectFeaturesUsed(Decl *decl, InsertOrRemove operation) {
437+
// Count feature usage in an ABI decl as feature usage by the API, not itself,
438+
// since we can't use `#if` inside an @abi attribute.
439+
Decl *abiDecl = nullptr;
440+
if (auto abiAttr = getABIAttr(decl)) {
441+
if (abiAttr->isInverse())
442+
return;
443+
abiDecl = abiAttr->abiDecl;
444+
}
445+
446+
#define CHECK(Function) (Function(decl) || (abiDecl && Function(abiDecl)))
447+
#define CHECK_ARG(Function, Arg) (Function(Arg, decl) || (abiDecl && Function(Arg, abiDecl)))
448+
428449
// Go through each of the features, checking whether the
429450
// declaration uses that feature.
430451
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
431-
if (usesFeature##FeatureName(decl)) \
452+
if (CHECK(usesFeature##FeatureName)) \
432453
collectRequiredFeature(Feature::FeatureName, operation);
433454
#define SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
434-
if (usesFeature##FeatureName(decl)) { \
435-
if (disallowFeatureSuppression(#FeatureName, decl)) \
455+
if (CHECK(usesFeature##FeatureName)) { \
456+
if (CHECK_ARG(disallowFeatureSuppression, #FeatureName)) \
436457
collectRequiredFeature(Feature::FeatureName, operation); \
437458
else \
438459
collectSuppressibleFeature(Feature::FeatureName, operation); \
439460
}
440461
#define CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
441-
if (usesFeature##FeatureName(decl)) { \
442-
if (allowFeatureSuppression(#FeatureName, decl)) \
462+
if (CHECK(usesFeature##FeatureName)) { \
463+
if (CHECK_ARG(allowFeatureSuppression, #FeatureName)) \
443464
collectSuppressibleFeature(Feature::FeatureName, operation); \
444465
else \
445466
collectRequiredFeature(Feature::FeatureName, operation); \
446467
}
447468
#include "swift/Basic/Features.def"
469+
#undef CHECK
470+
#undef CHECK_ARG
448471
}
449472

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