Skip to content

Commit a5185af

Browse files
committed
Print @abi into module interface (suppressibly)
1 parent 1faa099 commit a5185af

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
@@ -437,7 +437,7 @@ EXPERIMENTAL_FEATURE(CoroutineAccessorsAllocateInCallee, false)
437437
EXPERIMENTAL_FEATURE(GenerateForceToMainActorThunks, false)
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
@@ -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.
@@ -3235,6 +3268,16 @@ suppressingFeatureCoroutineAccessors(PrintOptions &options,
32353268
action();
32363269
}
32373270

3271+
static void
3272+
suppressingFeatureABIAttribute(PrintOptions &options,
3273+
llvm::function_ref<void()> action) {
3274+
llvm::SaveAndRestore<bool> scope(options.PrintSyntheticSILGenName, true);
3275+
unsigned originalExcludeAttrCount = options.ExcludeAttrList.size();
3276+
options.ExcludeAttrList.push_back(DeclAttrKind::ABI);
3277+
action();
3278+
options.ExcludeAttrList.resize(originalExcludeAttrCount);
3279+
}
3280+
32383281
/// Suppress the printing of a particular feature.
32393282
static void suppressingFeature(PrintOptions &options, Feature feature,
32403283
llvm::function_ref<void()> action) {
@@ -4007,6 +4050,8 @@ void PrintAST::printOneParameter(const ParamDecl *param,
40074050
void PrintAST::printParameterList(ParameterList *PL,
40084051
ArrayRef<AnyFunctionType::Param> params,
40094052
bool isAPINameByDefault) {
4053+
llvm::SaveAndRestore<bool> scope(Options.PrintSyntheticSILGenName, false);
4054+
40104055
Printer.printStructurePre(PrintStructureKind::FunctionParameterList);
40114056
SWIFT_DEFER {
40124057
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
@@ -1834,7 +1834,13 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
18341834
auto *attr = cast<ABIAttr>(this);
18351835
Printer << "@abi(";
18361836
ASSERT(!attr->isInverse() && "should be skipped above");
1837-
if (attr->abiDecl)
1837+
Decl *abiDecl = attr->abiDecl;
1838+
if (abiDecl && Options.ExplodePatternBindingDecls
1839+
&& isa<PatternBindingDecl>(abiDecl) && D && isa<VarDecl>(D))
1840+
abiDecl = cast<PatternBindingDecl>(abiDecl)
1841+
->getVarAtSimilarStructuralPosition(
1842+
const_cast<VarDecl *>(cast<VarDecl>(D)));
1843+
if (abiDecl)
18381844
attr->abiDecl->print(Printer, Options);
18391845
Printer << ")";
18401846

lib/AST/FeatureSet.cpp

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

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

302311
UNINTERESTING_FEATURE(WarnUnsafe)
@@ -400,26 +409,40 @@ static bool allowFeatureSuppression(StringRef featureName, Decl *decl) {
400409
/// Go through all the features used by the given declaration and
401410
/// either add or remove them to this set.
402411
void FeatureSet::collectFeaturesUsed(Decl *decl, InsertOrRemove operation) {
412+
// Count feature usage in an ABI decl as feature usage by the API, not itself,
413+
// since we can't use `#if` inside an @abi attribute.
414+
Decl *abiDecl = nullptr;
415+
if (auto abiAttr = getABIAttr(decl)) {
416+
if (abiAttr->isInverse())
417+
return;
418+
abiDecl = abiAttr->abiDecl;
419+
}
420+
421+
#define CHECK(Function) (Function(decl) || (abiDecl && Function(abiDecl)))
422+
#define CHECK_ARG(Function, Arg) (Function(Arg, decl) || (abiDecl && Function(Arg, abiDecl)))
423+
403424
// Go through each of the features, checking whether the
404425
// declaration uses that feature.
405426
#define LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
406-
if (usesFeature##FeatureName(decl)) \
427+
if (CHECK(usesFeature##FeatureName)) \
407428
collectRequiredFeature(Feature::FeatureName, operation);
408429
#define SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
409-
if (usesFeature##FeatureName(decl)) { \
410-
if (disallowFeatureSuppression(#FeatureName, decl)) \
430+
if (CHECK(usesFeature##FeatureName)) { \
431+
if (CHECK_ARG(disallowFeatureSuppression, #FeatureName)) \
411432
collectRequiredFeature(Feature::FeatureName, operation); \
412433
else \
413434
collectSuppressibleFeature(Feature::FeatureName, operation); \
414435
}
415436
#define CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE(FeatureName, SENumber, Description) \
416-
if (usesFeature##FeatureName(decl)) { \
417-
if (allowFeatureSuppression(#FeatureName, decl)) \
437+
if (CHECK(usesFeature##FeatureName)) { \
438+
if (CHECK_ARG(allowFeatureSuppression, #FeatureName)) \
418439
collectSuppressibleFeature(Feature::FeatureName, operation); \
419440
else \
420441
collectRequiredFeature(Feature::FeatureName, operation); \
421442
}
422443
#include "swift/Basic/Features.def"
444+
#undef CHECK
445+
#undef CHECK_ARG
423446
}
424447

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