Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-7396] [Exclusivity] SILGen loads entire struct when reading captured 'let' stored property #49939

Open
devincoughlin opened this issue Apr 10, 2018 · 0 comments

Comments

@devincoughlin
Copy link
Member

@devincoughlin devincoughlin commented Apr 10, 2018

Previous ID SR-7396
Radar rdar://problem/35561050
Original Reporter @devincoughlin
Type Bug
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, SILGen
Assignee None
Priority Medium

md5: 7e5c282beaaefdc99de4b06445d4bbb6

Issue Description:

When SILGen reads a captured ‘let’ stored property from a struct it loads the entire struct and then extracts the property value from the struct.

This causes unexpected exclusivity violations because to the programmer it looks like they are loading just the stored property.

Here is an example inspired by the Foundation overlay's Data Iterator:

func takesInoutAndClosure(_ p1: inout Int, _ p2: () -> ()) { }

public struct Iterator {
{{ private let _data: Int}}
{{ private var _buffer: Int}}

{{ public mutating func next() {}}
{{ takesInoutAndClosure(&_buffer) { // error: overlapping accesses to 'self._buffer'}}
{{ let _ = _data; // conflicting access (to all of ‘self’)}}
{{ }}}
{{ }}}
{{}}}

The closure in next() gets SILGen'd to:

// closure #​1 in Iterator.next()``sil private @$S1t8IteratorV4nextyyFyyXEfU_ : $@convention(thin) (@inout_aliasable Iterator) -> () {``// %0 // users: %2, %1``bb0(%0 : $*Iterator):{{ debug_value_addr %0 : $*Iterator, var, name "self", argno 1 // id: %1}}{{ %2 = begin_access [read] [unknown] %0 : $*Iterator // users: %4, %3}}{{ %3 = load [trivial] %2 : $*Iterator // user: %5}}{{ end_access %2 : $*Iterator // id: %4}}{{ %5 = struct_extract %3 : $Iterator, #Iterator._data}}{{ %6 = tuple () // user: %7}}{{ return %6 : $() // id: %7}}{{}}}

From John in an email:
> I think we could pretty easily change SILGen to only load the specific stored property here.

To prevent these exclusivity violations, the SILGen should instead look something like:

bb0(%0 : $*Iterator):
{{ %2 = begin_access [read] [unknown] %0 : $*Iterator}}
{{ %3 = struct_element_addr %6 : $*Iterator, #Iterator._data}}
{{ %4 = load [trivial] %23: $*Int}}
{{ end_access %2 : $*Iterator}}
{{ %6 = tuple ()}}
{{ return %6 : $()}}

In the Foundation overlay I've changed the let-bound variables in Data.Iterator to be 'var' to avoid the violation with #15823 We should revert that when this issue is fixed.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant