@@ -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+
164167The ` AccessedStorage ` and ` AccessPath ` types formalize memory access
165168in SIL. Given an address-typed SIL value, it is possible to
166169reliably identify the storage location of the accessed
@@ -193,17 +196,17 @@ address is immutable for the duration of its access scope
193196
194197Computing ` AccessedStorage ` and ` AccessPath ` for any given SIL address
195198involves 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
207210access "base", the outer-most "access" scope, and the "address" of a
208211memory 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
227241The 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
234247def-use chain. The reference root is the greatest common ancestor in
235248the 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
237250def-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
269282property 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
279301The 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 `
285308instruction. Therefore, we consider the ` alloc_box ` to be the base of
286309the access. Box storage does not apply to all box types or box
287310projections, which may instead originate from arguments or indirect
288311enums 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+
290319Typically, 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
294323types, and may traverse phis. For some kinds of storage, the base may
295324itself even be a non-address pointer. For phis that cannot be uniquely
296325resolved, 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
323352have a common base, then it is considered an invalid access (the
324353AccessedStorage 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
328357pointer phis unless they have a common base.
329358
330359Not 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
334363non-formal access, SIL verification is not as strict. An invalid
335364access is allowed, but handled conservatively. This is safe as long as
336365those 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
0 commit comments