AST: Allow @inline(__always)/@inline(never) to be applied to properties and subscripts

Previously we only permitted it on the accessor itself, but there is
no reason not to allow it on the storage declaration.

Fixes <https://bugs.swift.org/browse/SR-3624> / <rdar://problem/31865137>.
This commit is contained in:
Slava Pestov
2018-11-13 16:12:20 -05:00
parent f6c2caf64b
commit 6e4400567b
6 changed files with 50 additions and 96 deletions

View File

@@ -179,7 +179,7 @@ SIMPLE_DECL_ATTR(unsafe_no_objc_tagged_pointer, UnsafeNoObjCTaggedPointer,
UserInaccessible,
19)
DECL_ATTR(inline, Inline,
OnFunc | OnAccessor | OnConstructor,
OnVar | OnSubscript | OnAbstractFunction,
20)
DECL_ATTR(_semantics, Semantics,
OnAbstractFunction | OnSubscript |

View File

@@ -528,26 +528,47 @@ IsSerialized_t SILDeclRef::isSerialized() const {
return IsNotSerialized;
}
/// \brief True if the function has noinline attribute.
/// \brief True if the function has an @inline(never) attribute.
bool SILDeclRef::isNoinline() const {
if (!hasDecl())
return false;
if (auto InlineA = getDecl()->getAttrs().getAttribute<InlineAttr>())
if (InlineA->getKind() == InlineKind::Never)
auto *decl = getDecl();
if (auto *attr = decl->getAttrs().getAttribute<InlineAttr>())
if (attr->getKind() == InlineKind::Never)
return true;
if (auto *semanticsA = getDecl()->getAttrs().getAttribute<SemanticsAttr>())
if (semanticsA->Value.equals("keypath.entry"))
if (auto *accessorDecl = dyn_cast<AccessorDecl>(decl)) {
auto *storage = accessorDecl->getStorage();
if (auto *attr = storage->getAttrs().getAttribute<InlineAttr>())
if (attr->getKind() == InlineKind::Never)
return true;
}
if (auto *attr = decl->getAttrs().getAttribute<SemanticsAttr>())
if (attr->Value.equals("keypath.entry"))
return true;
return false;
}
/// \brief True if the function has noinline attribute.
/// \brief True if the function has the @inline(__always) attribute.
bool SILDeclRef::isAlwaysInline() const {
if (!hasDecl())
return false;
if (auto InlineA = getDecl()->getAttrs().getAttribute<InlineAttr>())
if (InlineA->getKind() == InlineKind::Always)
auto *decl = getDecl();
if (auto attr = decl->getAttrs().getAttribute<InlineAttr>())
if (attr->getKind() == InlineKind::Always)
return true;
if (auto *accessorDecl = dyn_cast<AccessorDecl>(decl)) {
auto *storage = accessorDecl->getStorage();
if (auto *attr = storage->getAttrs().getAttribute<InlineAttr>())
if (attr->getKind() == InlineKind::Always)
return true;
}
return false;
}

View File

@@ -1,4 +1,3 @@
// RUN: %target-swift-emit-silgen -module-name functions -Xllvm -sil-full-demangle -parse-stdlib -parse-as-library -enable-sil-ownership %s | %FileCheck %s
import Swift // just for Optional
@@ -422,27 +421,6 @@ func applyTransparent(_ x: Bool) -> Bool {
@inline(never)
func noinline_callee() {}
// CHECK-LABEL: sil hidden [always_inline] @$s9functions20always_inline_calleeyyF : $@convention(thin) () -> ()
@inline(__always)
func always_inline_callee() {}
// CHECK-LABEL: sil [always_inline] @$s9functions27public_always_inline_calleeyyF : $@convention(thin) () -> ()
@inline(__always)
public func public_always_inline_callee() {}
protocol AlwaysInline {
func alwaysInlined()
}
// CHECK-LABEL: sil hidden [always_inline] @$s9functions19AlwaysInlinedMemberV06alwaysC0{{[_0-9a-zA-Z]*}}F : $@convention(method) (AlwaysInlinedMember) -> () {
// protocol witness for functions.AlwaysInline.alwaysInlined <A : functions.AlwaysInline>(functions.AlwaysInline.Self)() -> () in conformance functions.AlwaysInlinedMember : functions.AlwaysInline in functions
// CHECK-LABEL: sil private [transparent] [thunk] [always_inline] @$s9functions19AlwaysInlinedMemberVAA0B6InlineA2aDP06alwaysC0{{[_0-9a-zA-Z]*}}FTW : $@convention(witness_method: AlwaysInline) (@in_guaranteed AlwaysInlinedMember) -> () {
struct AlwaysInlinedMember : AlwaysInline {
@inline(__always)
func alwaysInlined() {}
}
// CHECK-LABEL: sil hidden [Onone] @$s9functions10onone_funcyyF : $@convention(thin) () -> ()
@_optimize(none)
func onone_func() {}

View File

@@ -129,3 +129,21 @@ private class PrivateDerivedFromPublic : PublicBase {}
// CHECK-LABEL: sil private @$s19inlinable_attribute21PrivateDerivedFromUFI{{.+}}LLC5horseAdA5HorseC_tcfc : $@convention(method) (@owned Horse, @owned PrivateDerivedFromUFI) -> @owned PrivateDerivedFromUFI
private class PrivateDerivedFromUFI : UFIBase {}
// Make sure that nested functions are also serializable.
// CHECK-LABEL: sil [serialized] @$s19inlinable_attribute3basyyF
@inlinable
public func bas() {
// CHECK-LABEL: sil shared [serialized] @$s19inlinable_attribute3basyyF3zimL_yyF
func zim() {
// CHECK-LABEL: sil shared [serialized] @$s19inlinable_attribute3basyyF3zimL_yyF4zangL_yyF
func zang() { }
}
// CHECK-LABEL: sil shared [serialized] @$s19inlinable_attribute3bas{{[_0-9a-zA-Z]*}}U_
let zung = {
// CHECK-LABEL: sil shared [serialized] @$s19inlinable_attribute3basyyFyycfU_7zippityL_yyF
func zippity() { }
}
}

View File

@@ -1,63 +0,0 @@
// RUN: %target-swift-emit-silgen -enable-sil-ownership -module-name main %s | %FileCheck %s
internal func internalFunc() {}
// CHECK-LABEL: sil @$s4main3fooyyF
public func foo() {
// CHECK-LABEL: sil private [always_inline] @$s4main3foo{{[_0-9a-zA-Z]*}}zim
@inline(__always)
func zim() {
// CHECK-LABEL: sil private @$s4main3fooyyF3zimL_yyF4zangL_yyF
func zang() { internalFunc() }
internalFunc()
}
// CHECK-LABEL: sil private @$s4main3foo{{[_0-9a-zA-Z]*}}U_
let zung = {
// CHECK-LABEL: sil private [always_inline] @$s4main3fooyyFyycfU_7zippityL_yyF
@inline(__always)
func zippity() { internalFunc() }
internalFunc()
}
}
// CHECK-LABEL: sil hidden [always_inline] @$s4main3baryyF
@inline(__always)
internal func bar() {
// CHECK-LABEL: sil private [always_inline] @$s4main3baryyF3zimL_yyF
@inline(__always)
func zim() {
// CHECK-LABEL: sil private @$s4main3baryyF3zimL_yyF4zangL_yyF
func zang() { internalFunc() }
internalFunc()
}
// CHECK-LABEL: sil private @$s4main3bar{{[_0-9a-zA-Z]*}}U_
let zung = {
// CHECK-LABEL: sil private [always_inline] @$s4main3baryyFyycfU_7zippityL_yyF
@inline(__always)
func zippity() { internalFunc() }
internalFunc()
}
}
public func publicFunc() {}
// CHECK-LABEL: sil [serialized] [always_inline] @$s4main3basyyF
@inlinable @inline(__always)
public func bas() {
// CHECK-LABEL: sil shared [serialized] [always_inline] @$s4main3basyyF3zimL_yyF
@inline(__always)
func zim() {
// CHECK-LABEL: sil shared [serialized] @$s4main3basyyF3zimL_yyF4zangL_yyF
func zang() { publicFunc() }
publicFunc()
}
// CHECK-LABEL: sil shared [serialized] @$s4main3bas{{[_0-9a-zA-Z]*}}U_
let zung = {
// CHECK-LABEL: sil shared [serialized] [always_inline] @$s4main3basyyFyycfU_7zippityL_yyF
@inline(__always)
func zippity() { publicFunc() }
publicFunc()
}
}

View File

@@ -214,12 +214,12 @@ func func_type_attribute_with_space(x: @convention (c) () -> Int) {} // OK. Know
var thinFunc : @thin () -> () // expected-error {{attribute is not supported}}
@inline(never) func nolineFunc() {}
@inline(never) var noinlineVar : Int // expected-error {{'@inline(never)' attribute cannot be applied to this declaration}} {{1-16=}}
@inline(never) var noinlineVar : Int { return 0 }
@inline(never) class FooClass { // expected-error {{'@inline(never)' attribute cannot be applied to this declaration}} {{1-16=}}
}
@inline(__always) func AlwaysInlineFunc() {}
@inline(__always) var alwaysInlineVar : Int // expected-error {{'@inline(__always)' attribute cannot be applied to this declaration}} {{1-19=}}
@inline(__always) var alwaysInlineVar : Int { return 0 }
@inline(__always) class FooClass2 { // expected-error {{'@inline(__always)' attribute cannot be applied to this declaration}} {{1-19=}}
}