Skip to content

Commit 052d1e7

Browse files
committed
Print @abi into module interface (suppressibly)
1 parent 4e737d4 commit 052d1e7

File tree

6 files changed

+110
-12
lines changed

6 files changed

+110
-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
@@ -424,7 +424,7 @@ EXPERIMENTAL_FEATURE(UnspecifiedMeansMainActorIsolated, false)
424424
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(CoroutineAccessors, true)
425425

426426
/// Allow the @abi attribute.
427-
EXPERIMENTAL_FEATURE(ABIAttribute, true)
427+
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(ABIAttribute, true)
428428

429429
#undef EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE
430430
#undef EXPERIMENTAL_FEATURE

lib/AST/ASTPrinter.cpp

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

1252+
bool canPrintSyntheticSILGenName(const Decl *D) {
1253+
ASSERT(!D->getAttrs().hasAttribute<SILGenNameAttr>());
1254+
1255+
// Only print on functions, and only those functions with no barriers to use.
1256+
if (auto FD = dyn_cast<AbstractFunctionDecl>(D); !FD
1257+
|| FD->getAttrs().hasAttribute<BackDeployedAttr>()
1258+
|| FD->getOpaqueResultTypeDecl())
1259+
return false;
1260+
1261+
return true;
1262+
}
1263+
12521264
void PrintAST::printAttributes(const Decl *D) {
12531265
if (Options.SkipAttributes)
12541266
return;
@@ -1266,6 +1278,27 @@ void PrintAST::printAttributes(const Decl *D) {
12661278
// for each decl They cannot be shared across different decls.
12671279
assert(Options.ExcludeCustomAttrList.empty());
12681280

1281+
if (Options.PrintSyntheticSILGenName
1282+
&& !D->getAttrs().hasAttribute<SILGenNameAttr>()) {
1283+
if (canPrintSyntheticSILGenName(D)) {
1284+
auto mangledName = Mangle::ASTMangler().mangleAnyDecl(
1285+
cast<ValueDecl>(D), /*prefix=*/true,
1286+
/*respectOriginallyDefinedIn=*/true);
1287+
Printer.printAttrName("@_silgen_name");
1288+
Printer << "(";
1289+
Printer.printEscapedStringLiteral(mangledName);
1290+
Printer << ")\n";
1291+
}
1292+
else {
1293+
Printer.printAttrName("@available");
1294+
Printer << "(*, unavailable, message: ";
1295+
Printer.printEscapedStringLiteral(
1296+
"this compiler cannot match the ABI specified by the @abi attribute");
1297+
Printer << ")\n";
1298+
Options.ExcludeAttrList.push_back(DeclAttrKind::Available);
1299+
}
1300+
}
1301+
12691302
if (Options.PrintImplicitAttrs) {
12701303

12711304
// Don't print a redundant 'final' if we are printing a 'static' decl.
@@ -3237,6 +3270,16 @@ suppressingFeatureCoroutineAccessors(PrintOptions &options,
32373270
action();
32383271
}
32393272

3273+
static void
3274+
suppressingFeatureABIAttribute(PrintOptions &options,
3275+
llvm::function_ref<void()> action) {
3276+
llvm::SaveAndRestore<bool> scope(options.PrintSyntheticSILGenName, true);
3277+
unsigned originalExcludeAttrCount = options.ExcludeAttrList.size();
3278+
options.ExcludeAttrList.push_back(DeclAttrKind::ABI);
3279+
action();
3280+
options.ExcludeAttrList.resize(originalExcludeAttrCount);
3281+
}
3282+
32403283
/// Suppress the printing of a particular feature.
32413284
static void suppressingFeature(PrintOptions &options, Feature feature,
32423285
llvm::function_ref<void()> action) {
@@ -4009,6 +4052,8 @@ void PrintAST::printOneParameter(const ParamDecl *param,
40094052
void PrintAST::printParameterList(ParameterList *PL,
40104053
ArrayRef<AnyFunctionType::Param> params,
40114054
bool isAPINameByDefault) {
4055+
llvm::SaveAndRestore<bool> scope(Options.PrintSyntheticSILGenName, false);
4056+
40124057
Printer.printStructurePre(PrintStructureKind::FunctionParameterList);
40134058
SWIFT_DEFER {
40144059
Printer.printStructurePost(PrintStructureKind::FunctionParameterList);

lib/AST/Attr.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,7 @@ void DeclAttributes::print(ASTPrinter &Printer, const PrintOptions &Options,
10251025
AttributeVector attributes;
10261026
AttributeVector modifiers;
10271027
bool libraryLevelAPI =
1028-
D->getASTContext().LangOpts.LibraryLevel == LibraryLevel::API;
1028+
D && D->getASTContext().LangOpts.LibraryLevel == LibraryLevel::API;
10291029

10301030
for (auto DA : llvm::reverse(FlattenedAttrs)) {
10311031
// Don't skip implicit custom attributes. Custom attributes like global
@@ -1842,7 +1842,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
18421842
auto *attr = cast<ABIAttr>(this);
18431843
Printer << "@abi(";
18441844
ASSERT(!attr->isInverse() && "should be skipped above");
1845-
if (attr->abiDecl)
1845+
Decl *abiDecl = attr->abiDecl;
1846+
if (abiDecl && Options.ExplodePatternBindingDecls
1847+
&& isa<PatternBindingDecl>(abiDecl) && D && isa<VarDecl>(D))
1848+
abiDecl = cast<PatternBindingDecl>(abiDecl)
1849+
->getVarAtSimilarStructuralPosition(
1850+
const_cast<VarDecl *>(cast<VarDecl>(D)));
1851+
if (abiDecl)
18461852
attr->abiDecl->print(Printer, Options);
18471853
Printer << ")";
18481854

lib/AST/FeatureSet.cpp

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

295+
static ABIAttr *getABIAttr(Decl *decl) {
296+
if (auto pbd = dyn_cast<PatternBindingDecl>(decl))
297+
for (auto i : range(pbd->getNumPatternEntries()))
298+
if (auto anchorVar = pbd->getAnchoringVarDecl(i))
299+
return getABIAttr(anchorVar);
300+
// FIXME: EnumCaseDecl/EnumElementDecl
301+
302+
return decl->getAttrs().getAttribute<ABIAttr>();
303+
}
304+
295305
static bool usesFeatureABIAttribute(Decl *decl) {
296-
auto abiAttr = decl->getAttrs().getAttribute<ABIAttr>();
297-
return abiAttr && !abiAttr->isInverse();
306+
return getABIAttr(decl) != nullptr;
298307
}
299308

300309
UNINTERESTING_FEATURE(WarnUnsafe)
@@ -395,26 +404,40 @@ static bool allowFeatureSuppression(StringRef featureName, Decl *decl) {
395404
/// Go through all the features used by the given declaration and
396405
/// either add or remove them to this set.
397406
void FeatureSet::collectFeaturesUsed(Decl *decl, InsertOrRemove operation) {
407+
// Count feature usage in an ABI decl as feature usage by the API, not itself,
408+
// since we can't use `#if` inside an @abi attribute.
409+
Decl *abiDecl = nullptr;
410+
if (auto abiAttr = getABIAttr(decl)) {
411+
if (abiAttr->isInverse())
412+
return;
413+
abiDecl = abiAttr->abiDecl;
414+
}
415+
416+
#define CHECK(Function) (Function(decl) || (abiDecl && Function(abiDecl)))
417+
#define CHECK_ARG(Function, Arg) (Function(Arg, decl) || (abiDecl && Function(Arg, abiDecl)))
418+
398419
// Go through each of the features, checking whether the
399420
// declaration uses that feature.
400421
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
401-
if (usesFeature##FeatureName(decl)) \
422+
if (CHECK(usesFeature##FeatureName)) \
402423
collectRequiredFeature(Feature::FeatureName, operation);
403424
#define SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
404-
if (usesFeature##FeatureName(decl)) { \
405-
if (disallowFeatureSuppression(#FeatureName, decl)) \
425+
if (CHECK(usesFeature##FeatureName)) { \
426+
if (CHECK_ARG(disallowFeatureSuppression, #FeatureName)) \
406427
collectRequiredFeature(Feature::FeatureName, operation); \
407428
else \
408429
collectSuppressibleFeature(Feature::FeatureName, operation); \
409430
}
410431
#define CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
411-
if (usesFeature##FeatureName(decl)) { \
412-
if (allowFeatureSuppression(#FeatureName, decl)) \
432+
if (CHECK(usesFeature##FeatureName)) { \
433+
if (CHECK_ARG(allowFeatureSuppression, #FeatureName)) \
413434
collectSuppressibleFeature(Feature::FeatureName, operation); \
414435
else \
415436
collectRequiredFeature(Feature::FeatureName, operation); \
416437
}
417438
#include "swift/Basic/Features.def"
439+
#undef CHECK
440+
#undef CHECK_ARG
418441
}
419442

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

test/ModuleInterface/attrs.swift

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
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
44

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

0 commit comments

Comments
 (0)