Skip to content

Commit 2137e41

Browse files
committed
Swift SIL: add ProjectedValue.
A projected value consists of the original value and a projection path. For example, if the `value` is of type `struct S { var x: Int }` and `path` is `s0`, then the projected value represents field `x` of the original value. Also, use ProjectedValue instead of AccessStoragePath.
1 parent e06d1c6 commit 2137e41

File tree

4 files changed

+57
-32
lines changed

4 files changed

+57
-32
lines changed

SwiftCompilerSources/Sources/Optimizer/TestPasses/AccessDumper.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ let accessDumper = FunctionPass(name: "dump-access", {
5050

5151
private struct AccessStoragePathVisitor : AccessStoragePathWalker {
5252
var walkUpCache = WalkerCache<Path>()
53-
mutating func visit(access: AccessStoragePath) {
54-
print(" Storage: \(access.storage)")
55-
print(" Path: \"\(access.path)\"")
53+
mutating func visit(accessStoragePath: ProjectedValue) {
54+
print(" Storage: \(accessStoragePath.value)")
55+
print(" Path: \"\(accessStoragePath.path)\"")
5656
}
5757
}
5858

SwiftCompilerSources/Sources/Optimizer/Utilities/AccessUtils.swift

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
// - `AccessPath`: a pair of an `AccessBase` and `SmallProjectionPath` with the
1616
// the path describing the specific address (in terms of projections) of the
1717
// access.
18-
// - `AccessStoragePath`: identifies the reference (or a value which contains a
19-
// reference) an address originates from.
18+
// - Access storage path (which is of type `ProjectedValue`): identifies the
19+
// reference (or a value which contains a reference) an address originates from.
2020
//
2121
// The snippet below shows the relationship between the access concepts.
2222
// ```
23-
// %ref = struct_extract %value, #f1 AccessStoragePath
23+
// %ref = struct_extract %value, #f1 access storage path
2424
// %base = ref_element_addr %ref, #f2 AccessBase AccessPath |
2525
// %scope = begin_access %base AccessScope | |
2626
// %t = tuple_element_addr %scope, 0 | |
@@ -253,22 +253,6 @@ struct AccessPath : CustomStringConvertible {
253253
}
254254
}
255255

256-
/// An `AccessStoragePath` is the reference (or a value which contains a reference)
257-
/// an address originates from.
258-
/// In the following example the `storage` is `contains_ref` with `path` `"s0.c0.s0"`
259-
/// ```
260-
/// %ref = struct_extract %contains_ref : $S, #S.l
261-
/// %base = ref_element_addr %ref : $List, #List.x
262-
/// %addr = struct_element_addr %base : $X, #X.e
263-
/// store %v to [trivial] %addr : $*Int
264-
/// ```
265-
struct AccessStoragePath {
266-
let storage: Value
267-
268-
/// Only valid paths are: `"<sequence of value projections>.<one reference projection>.<sequence of address projections>"`
269-
let path: SmallProjectionPath
270-
}
271-
272256
private func canBeOperandOfIndexAddr(_ value: Value) -> Bool {
273257
switch value {
274258
case is IndexAddrInst, is RefTailAddrInst, is PointerToAddressInst:
@@ -506,10 +490,19 @@ extension Value {
506490
}
507491
}
508492

509-
/// A ValueUseDef walker that identifies which values a reference of an access path might
510-
/// originate from.
493+
/// A ValueUseDef walker that that visits access storage paths of an address.
494+
///
495+
/// An access storage path is the reference (or a value which contains a reference)
496+
/// an address originates from.
497+
/// In the following example the `storage` is `contains_ref` with `path` `"s0.c0.s0"`
498+
/// ```
499+
/// %ref = struct_extract %contains_ref : $S, #S.l
500+
/// %base = ref_element_addr %ref : $List, #List.x
501+
/// %addr = struct_element_addr %base : $X, #X.e
502+
/// store %v to [trivial] %addr : $*Int
503+
/// ```
511504
protocol AccessStoragePathWalker : ValueUseDefWalker where Path == SmallProjectionPath {
512-
mutating func visit(access: AccessStoragePath)
505+
mutating func visit(accessStoragePath: ProjectedValue)
513506
}
514507

515508
extension AccessStoragePathWalker {
@@ -534,7 +527,7 @@ extension AccessStoragePathWalker {
534527
}
535528

536529
mutating func rootDef(value: Value, path: SmallProjectionPath) -> WalkResult {
537-
visit(access: AccessStoragePath(storage: value, path: path))
530+
visit(accessStoragePath: value.at(path))
538531
return .continueWalk
539532
}
540533
}

SwiftCompilerSources/Sources/SIL/Value.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,30 @@ public func !=(_ lhs: Value, _ rhs: Value) -> Bool {
118118
return !(lhs === rhs)
119119
}
120120

121+
/// A projected value, which is defined by the original value and a projection path.
122+
///
123+
/// For example, if the `value` is of type `struct S { var x: Int }` and `path` is `s0`,
124+
/// then the projected value represents field `x` of the original value.
125+
/// An empty path means represents the "whole" original value.
126+
///
127+
public struct ProjectedValue {
128+
public let value: Value
129+
public let path: SmallProjectionPath
130+
}
131+
132+
extension Value {
133+
/// Returns a projected value, defined by this value and `path`.
134+
public func at(_ path: SmallProjectionPath) -> ProjectedValue {
135+
ProjectedValue(value: self, path: path)
136+
}
137+
138+
/// Returns a projected value, defined by this value and path containig a single field of `kind` and `index`.
139+
public func at(_ kind: SmallProjectionPath.FieldKind, index: Int = 0) -> ProjectedValue {
140+
ProjectedValue(value: self, path: SmallProjectionPath(kind, index: index))
141+
}
142+
}
143+
144+
121145
extension BridgedValue {
122146
public func getAs<T: AnyObject>(_ valueType: T.Type) -> T { obj.getAs(T.self) }
123147

docs/SIL-Utilities.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,20 @@ To be used for all kind of basic-block work-list algorithms.
4040
**Related C++ utilities:** `BasicBlockWorklist`
4141
**Status:** done
4242

43+
## SIL data structures
44+
45+
#### `SmallProjectionPath`
46+
Describes a path of projections.
47+
48+
**Related C++ utilities:** `AccessPath`, `ProjectionPath`
49+
**Status:** done
50+
51+
### `ProjectedValue`
52+
A projected value is defined by the original value and a projection path.
53+
54+
**Related C++ utilities:** `AccessPath`
55+
**Status:** done
56+
4357
## Building SIL
4458

4559
#### `static Builder.insert(after:, insertFunc: (Builder) -> ())`
@@ -61,12 +75,6 @@ This consists of four protocols, which can be implemented to walk up or down the
6175
**Related C++ utilities:** `AccessPath`, `RCIdentityAnalysis`, various def-use/use-def walkers in optimization passes.
6276
**Status:** done
6377

64-
#### `SmallProjectionPath`
65-
Describes a path of projections.
66-
67-
**Related C++ utilities:** `AccessPath`, `ProjectionPath`
68-
**Status:** done
69-
7078
#### `EscapeInfo`
7179
Escape analysis, which is used e.g. in stack promotion or alias analysis.
7280

0 commit comments

Comments
 (0)