Files
swift-mirror/test/IRGen/readonly.sil
Roman Levenstein 1180c3d5da Do not automatically map Swfit @effects(readonly) to LLVM's readonly attribute
Swift's readonly and readnone should not be automatically mapped to LLVM's readonly.
Swift SIL optimizer relies on @effects(readonly) to remove e.g. dead code remaining
from initializers of strings or dictionaries of variables that are not used. But
those initializers are often not really readonly in terms of LLVM IR. For
example, the Dictionary.init() is marked as @effects(readonly) in Swift, but it
does invoke reference-counting operations. As a result, it leads to miscompiles
and runtime crashes.

In the future, we may add the functionality to analyze the body of the function
and if we can prove that is really readonly, we can map it to the LLVM readonly
attribute.

I checked that removal of this mapping does not affect the performance of any of
our existing benchmarks.

Fixes rdar://problem/28830504
2017-02-17 16:55:33 -08:00

68 lines
2.1 KiB
Plaintext

// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil -emit-ir %s | %FileCheck %s
//sil_stage canonical
import Builtin
import Swift
import SwiftShims
private class XXX{}
sil @XXX_dtor : $@convention(method) (@owned XXX) -> ()
sil @XXX_ctor : $@convention(method) (@owned XXX) -> @owned XXX
// CHECK: target datalayout
// No @owned or @out parameters -- function is not read only at LLVM level,
// because Swift level read only attribute is not automatically mapped
// to the LLVM read only attribute, unless IRGen can prove by analyzing
// the function body that this function is really read only.
// CHECK-NOT: ; Function Attrs: readonly
// CHECK: define{{( protected)?}} swiftcc void @function_foo(
sil [readonly] @function_foo : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = tuple ()
return %1 : $()
}
// No @owned or @out parameters -- function is not read only at LLVM level,
// because Swift level read none attribute is not automatically mapped
// to the LLVM read only attribute, unless IRGen can prove by analyzing
// the function body that this function is really read only or read none.
// CHECK-NOT: ; Function Attrs: readonly
// CHECK: define{{( protected)?}} swiftcc void @function_foo2(
sil [readnone] @function_foo2 : $@convention(thin) (Int) -> () {
bb0(%0 : $Int):
%1 = tuple ()
return %1 : $()
}
// There's an @owned parameter, and destructors can call arbitrary code
// -- function is not read only at LLVM level
// CHECK-NOT: ; Function Attrs: readonly
// CHECK: define{{( protected)?}} swiftcc void @function_bar(
sil [readonly] @function_bar : $@convention(thin) (@owned XXX) -> () {
bb0(%0 : $XXX):
strong_release %0 : $XXX
%1 = tuple ()
return %1 : $()
}
// There's an @out parameter -- function is not read only at LLVM level
// CHECK-NOT: ; Function Attrs: readonly
// CHECK: define{{( protected)?}} swiftcc void @function_baz(
sil [readonly] @function_baz : $@convention(thin) () -> (@out Any) {
bb0(%0 : $*Any):
init_existential_addr %0 : $*Any, $()
%1 = tuple ()
return %1 : $()
}
sil_vtable XXX {
#XXX.deinit!deallocator: XXX_dtor
#XXX.init!initializer.1: XXX_ctor
}