Skip to content

Commit a93a1f8

Browse files
authored
Merge pull request swiftlang#38797 from atrick/ossa-isborrowedaddress
OSSA support for Box types. AccessedStorage Box handling. isBorrowedAddress utility.
2 parents f3aa228 + a6cb545 commit a93a1f8

16 files changed

+294
-186
lines changed

docs/SILProgrammersManual.md

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ idioms, it becomes overly burdensome to evolve these APIs over time.
161161

162162
## `AccessedStorage` and `AccessPath`
163163

164+
TODO: move this section to a separate document and refer to it from
165+
SIL.rst.
166+
164167
The `AccessedStorage` and `AccessPath` types formalize memory access
165168
in SIL. Given an address-typed SIL value, it is possible to
166169
reliably identify the storage location of the accessed
@@ -193,17 +196,17 @@ address is immutable for the duration of its access scope
193196

194197
Computing `AccessedStorage` and `AccessPath` for any given SIL address
195198
involves a use-def traversal to determine the origin of the
196-
address. It may traverse operations on address, pointer, box, and
197-
reference types. The logic that formalizes which SIL operations may be
198-
involved in the def-use chain is encapsulated with the
199-
`AccessUseDefChainVisitor`. The traversal can be customized by
200-
implementing this visitor. Customization is not expected to change the
201-
meaning of AccessedStorage or AccessPath. Rather, it is intended for
202-
additional pass-specific book-keeping or for higher-level convenience
203-
APIs that operate on the use-def chain bypassing AccessedStorage
204-
completely.
205-
206-
Access def-use chains are divided by four points: the "root", the
199+
address. It may traverse operations on values of type address,
200+
Builtin.RawPointer, box, and reference. The logic that
201+
formalizes which SIL operations may be involved in the def-use chain
202+
is encapsulated with the `AccessUseDefChainVisitor`. The traversal can
203+
be customized by implementing this visitor. Customization is not
204+
expected to change the meaning of AccessedStorage or
205+
AccessPath. Rather, it is intended for additional pass-specific
206+
book-keeping or for higher-level convenience APIs that operate on the
207+
use-def chain bypassing AccessedStorage completely.
208+
209+
Access def-use chains are divided by four points: the object "root", the
207210
access "base", the outer-most "access" scope, and the "address" of a
208211
memory operation. For example:
209212
```
@@ -222,18 +225,28 @@ memory operation. For example:
222225
end_access %access : $*S
223226
```
224227

228+
OR
229+
230+
```
231+
%root = alloc_box $S
232+
%base = project_box %root : ${ var S }
233+
%access = begin_access [read] [static] %base : $*S
234+
%address = struct_element_addr %access : $*S, #.field
235+
%value = load [trivial] %address : $*Int64
236+
end_access %access : $*S
237+
```
238+
225239
#### Reference root
226240

227241
The first part of the def-use chain computes the formal access base
228-
from the root of the object (e.g. `alloc_ref ->
229-
ref_element_addr`). The reference root might be a locally allocated
230-
object, a function argument, a function result, or a reference loaded
231-
from storage. There is no enforcement on the type of operation that
232-
can produce a reference; however, only reference types or
233-
Builtin.BridgeObject types are only allowed in this part of the
242+
from the root of the object (e.g. `alloc_ref -> ref_element_addr` and
243+
`alloc_box -> project_box`). The reference root might be a locally
244+
allocated object, a function argument, a function result, or a
245+
reference loaded from storage. There is no enforcement on the type of
246+
operation that can produce a reference; however, only reference types, Builtin.BridgeObject types, and box types are allowed in this part of the
234247
def-use chain. The reference root is the greatest common ancestor in
235248
the def-use graph that can identify an object by a single SILValue. If
236-
the root as an `alloc_ref`, then it is *uniquely identified*. The
249+
the root is an `alloc_ref`, then it is *uniquely identified*. The
237250
def-use chain from the root to the base may contain reference casts
238251
(`isRCIdentityPreservingCast`) and phis.
239252

@@ -268,29 +281,45 @@ formal access base. The reference root is only one component of an
268281
`AccessedStorage` location. AccessedStorage also identifies the class
269282
property being accessed within that object.
270283

284+
A reference root may be borrowed, so the use-def path from the base to
285+
the root may cross a borrow scope. This means that uses of one base
286+
may not be replaced with a different base even if it has the same
287+
AccessedStorage because they may not be contained within the same
288+
borrow scope. However, this is the only part of the access path that
289+
may be borrowed. Address uses with the same base can be substituted
290+
without checking the borrow scope.
291+
271292
#### Access base
272293

273-
The access base is the SILValue produced by an instruction that
274-
directly identifies the kind of storage being accessed without further
275-
use-def traversal. Common access bases are `alloc_box`, `alloc_stack`,
276-
`global_addr`, `ref_element_addr`, and function arguments (see
294+
The access base is the address or Builtin.RawPointer type SILValue
295+
produced by an instruction that directly identifies the kind of
296+
storage being accessed without further use-def traversal. Common
297+
access bases are `alloc_stack`, `global_addr`,
298+
`ref_element_addr`, `project_box`, and function arguments (see
277299
`AccessedStorage::Kind`).
278300

279301
The access base is the same as the "root" SILValue for all storage
280-
kinds except global and class storage. Global storage has no root. For
281-
class storage the root is the SILValue that identifies object,
282-
described as the "reference root" above.
302+
kinds except global and reference storage. Reference storage includes
303+
class, tail and box storage. Global storage has no root. For reference
304+
storage the root is the SILValue that identifies object, described as
305+
the "reference root" above.
283306

284307
"Box" storage is uniquely identified by an `alloc_box`
285308
instruction. Therefore, we consider the `alloc_box` to be the base of
286309
the access. Box storage does not apply to all box types or box
287310
projections, which may instead originate from arguments or indirect
288311
enums for example.
289312

313+
An access scope, identified by a `begin_access` marker, may only occur
314+
on the def-use path between the access base and any address
315+
projections. The def-use path from the root to the base cannot cross
316+
an access scope. Likewise, the def-use between an access projection
317+
and the memory operation cannot cross an access scope.
318+
290319
Typically, the base is the address-type source operand of a
291320
`begin_access`. However, the path from the access base to the
292321
`begin_access` may include *storage casts* (see
293-
`isAccessedStorageCast`). It may involve address, pointer, and box
322+
`isAccessedStorageCast`). It may involve address an pointer
294323
types, and may traverse phis. For some kinds of storage, the base may
295324
itself even be a non-address pointer. For phis that cannot be uniquely
296325
resolved, the base may even be a box type.
@@ -322,9 +351,9 @@ which address storage is always uniquely determined. Currently, if a
322351
(non-address) phi on the access path from `base` to `access` does not
323352
have a common base, then it is considered an invalid access (the
324353
AccessedStorage object is not valid). SIL verification ensures that a
325-
formal access always has valid AccessedStorage (WIP). In other words, the
326-
source of a `begin_access` marker must be a single, non-phi base. In
327-
the future, for further simplicity, we may generally disallow box and
354+
formal access always has valid AccessedStorage (WIP). In other words,
355+
the source of a `begin_access` marker must be a single, non-phi
356+
base. In the future, for further simplicity, we may also disallow
328357
pointer phis unless they have a common base.
329358

330359
Not all SIL memory access is part of a formal access, but the
@@ -334,8 +363,8 @@ the use-def search does not begin at a `begin_access` marker. For
334363
non-formal access, SIL verification is not as strict. An invalid
335364
access is allowed, but handled conservatively. This is safe as long as
336365
those non-formal accesses can never alias with class and global
337-
storage. Class and global access is always guarded by formal access
338-
markers--at least until static markers are stripped from SIL.
366+
storage. Class and global access must always be guarded by formal
367+
access markers--at least until static markers are stripped from SIL.
339368

340369
#### Nested access
341370

include/swift/SIL/InstructionUtils.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ SILValue getUnderlyingObject(SILValue V);
2727

2828
SILValue getUnderlyingObjectStopAtMarkDependence(SILValue V);
2929

30-
/// Given an address look through address to address projections and indexing
31-
/// insts.
32-
SILValue getUnderlyingObjectStoppingAtObjectToAddrProjections(SILValue v);
33-
3430
SILValue stripSinglePredecessorArgs(SILValue V);
3531

3632
/// Return the underlying SILValue after stripping off all casts from the

0 commit comments

Comments
 (0)