Skip to content

Commit 0e790fc

Browse files
committed
SIL: support vector_base_addr in SmallProjectionPath
Add a `vectorBase` field kind which corresponds to `vector_base_addr`. Also, improve `mayOverlap`: it didn't catch the case that the first element of a vector cannot overlap with another element.
1 parent b3087e3 commit 0e790fc

File tree

1 file changed

+39
-12
lines changed

1 file changed

+39
-12
lines changed

SwiftCompilerSources/Sources/SIL/Utilities/SmallProjectionPath.swift

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,15 +83,17 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
8383
// This and all following kinds (we'll add in the future) cannot have a field index.
8484
case tailElements = 0x07 // (0 << 3) | 0x7 A tail allocated element of a class: syntax `ct`
8585
case existential = 0x0f // (1 << 3) | 0x7 A concrete value projected out of an existential: synatx 'x'
86-
case anyClassField = 0x17 // (2 << 3) | 0x7 Any class field, including tail elements: syntax `c*`
87-
case anyIndexedElement = 0x1f // (3 << 3) | 0x7 An unknown offset into an array of elements.
86+
case vectorBase = 0x17 // (2 << 3) | 0x7 The base element of a vector: synatx 'b'
87+
case anyClassField = 0x1f // (3 << 3) | 0x7 Any class field, including tail elements: syntax `c*`
88+
case anyIndexedElement = 0x27 // (4 << 3) | 0x7 An unknown offset into an array of elements.
8889
// There must not be two successive element indices in the path.
89-
case anyValueFields = 0x27 // (4 << 3) | 0x7 Any number of any value fields (struct, tuple, enum): syntax `v**`
90-
case anything = 0x2f // (5 << 3) | 0x7 Any number of any fields: syntax `**`
90+
case anyValueFields = 0x2f // (5 << 3) | 0x7 Any number of any value fields (struct, tuple, enum): syntax `v**`
91+
case anything = 0x37 // (6 << 3) | 0x7 Any number of any fields: syntax `**`
9192

9293
public var isValueField: Bool {
9394
switch self {
94-
case .anyValueFields, .structField, .tupleField, .enumCase, .indexedElement, .anyIndexedElement, .existential:
95+
case .structField, .tupleField, .enumCase, .indexedElement, .existential, .vectorBase,
96+
.anyValueFields, .anyIndexedElement:
9597
return true
9698
case .root, .anything, .anyClassField, .classField, .tailElements:
9799
return false
@@ -102,7 +104,8 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
102104
switch self {
103105
case .anyClassField, .classField, .tailElements:
104106
return true
105-
case .root, .anything, .anyValueFields, .structField, .tupleField, .enumCase, .indexedElement, .anyIndexedElement, .existential:
107+
case .root, .anything, .anyValueFields, .structField, .tupleField, .enumCase, .indexedElement,
108+
.anyIndexedElement, .existential, .vectorBase:
106109
return false
107110
}
108111
}
@@ -140,6 +143,7 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
140143
case .classField: s = "c\(idx)"
141144
case .tailElements: s = "ct"
142145
case .existential: s = "x"
146+
case .vectorBase: s = "b"
143147
case .indexedElement: s = "i\(idx)"
144148
case .anyIndexedElement: s = "i*"
145149
case .anything: s = "**"
@@ -398,7 +402,7 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
398402
return subPath.matches(pattern: subPattern)
399403
case .anyIndexedElement:
400404
return popIndexedElements().matches(pattern: subPattern)
401-
case .structField, .tupleField, .enumCase, .classField, .tailElements, .indexedElement, .existential:
405+
case .structField, .tupleField, .enumCase, .classField, .tailElements, .indexedElement, .existential, .vectorBase:
402406
let (kind, index, subPath) = pop()
403407
if kind != patternKind || index != patternIdx { return false }
404408
return subPath.matches(pattern: subPattern)
@@ -478,8 +482,18 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
478482
}
479483
if (lhsKind == rhsKind && lhsIdx == rhsIdx) ||
480484
(lhsKind == .anyClassField && rhsKind.isClassField) ||
481-
(lhsKind.isClassField && rhsKind == .anyClassField) {
482-
return pop(numBits: lhsBits).mayOverlap(with: rhs.pop(numBits: rhsBits))
485+
(lhsKind.isClassField && rhsKind == .anyClassField)
486+
{
487+
let poppedPath = pop(numBits: lhsBits)
488+
let rhsPoppedPath = rhs.pop(numBits: rhsBits)
489+
// Check for the case of overlapping the first element of a vector with another element.
490+
// Note that the index of `.indexedElement` cannot be 0.
491+
if (poppedPath.isEmpty && rhsPoppedPath.pop().kind == .indexedElement) ||
492+
(rhsPoppedPath.isEmpty && poppedPath.pop().kind == .indexedElement)
493+
{
494+
return false
495+
}
496+
return poppedPath.mayOverlap(with: rhsPoppedPath)
483497
}
484498
return false
485499
}
@@ -496,7 +510,7 @@ public struct SmallProjectionPath : Hashable, CustomStringConvertible, NoReflect
496510
switch lhsKind {
497511
case .root:
498512
return rhs
499-
case .classField, .tailElements, .structField, .tupleField, .enumCase, .existential, .indexedElement:
513+
case .classField, .tailElements, .structField, .tupleField, .enumCase, .existential, .indexedElement, .vectorBase:
500514
let (rhsKind, rhsIdx, rhsBits) = rhs.top
501515
if lhsKind == rhsKind && lhsIdx == rhsIdx {
502516
return pop(numBits: lhsBits).subtract(from: rhs.pop(numBits: rhsBits))
@@ -601,6 +615,8 @@ extension StringParser {
601615
entries.append((.tailElements, 0))
602616
} else if consume("x") {
603617
entries.append((.existential, 0))
618+
} else if consume("b") {
619+
entries.append((.vectorBase, 0))
604620
} else if consume("c") {
605621
guard let idx = consumeInt(withWhiteSpace: false) else {
606622
try throwError("expected class field index")
@@ -701,7 +717,8 @@ extension SmallProjectionPath {
701717
.push(.enumCase, index: 6)
702718
.push(.anyClassField)
703719
.push(.tupleField, index: 2))
704-
testParse("i3.x.i*", expect: SmallProjectionPath(.anyIndexedElement)
720+
testParse("i3.x.b.i*", expect: SmallProjectionPath(.anyIndexedElement)
721+
.push(.vectorBase)
705722
.push(.existential)
706723
.push(.indexedElement, index: 3))
707724

@@ -739,6 +756,8 @@ extension SmallProjectionPath {
739756
testMerge("i*", "i2", expect: "i*")
740757
testMerge("s0.i*.e3", "s0.e3", expect: "s0.i*.e3")
741758
testMerge("i*", "v**", expect: "v**")
759+
testMerge("s0.b.i1", "s0.b.i0", expect: "s0.b.i*")
760+
testMerge("s0.b", "s0.1", expect: "s0.v**")
742761

743762
testMerge("ct.s0.e0.v**.c0", "ct.s0.e0.v**.c0", expect: "ct.s0.e0.v**.c0")
744763
testMerge("ct.s0.s0.c0", "ct.s0.e0.s0.c0", expect: "ct.s0.v**.c0")
@@ -813,6 +832,7 @@ extension SmallProjectionPath {
813832
testMatch("s1.v**", "s0.**", expect: false)
814833
testMatch("s0.**", "s0.v**", expect: false)
815834
testMatch("s0.s1", "s0.i*.s1", expect: true)
835+
testMatch("s0.b.s1", "s0.b.i*.s1", expect: true)
816836
}
817837

818838
func testMatch(_ lhsStr: String, _ rhsStr: String, expect: Bool) {
@@ -847,6 +867,13 @@ extension SmallProjectionPath {
847867
testOverlap("i1", "i*", expect: true)
848868
testOverlap("i1", "v**", expect: true)
849869
testOverlap("s0.i*.s1", "s0.s1", expect: true)
870+
testOverlap("s0.b.s1", "s0.b.i*.s1", expect: true)
871+
testOverlap("s0.b.i0.s1", "s0.b.i1.s1", expect: false)
872+
testOverlap("s0.b.i2.s1", "s0.b.i1.s1", expect: false)
873+
testOverlap("s0.b.s1", "s0.b.i0.s1", expect: true)
874+
testOverlap("s0.b", "s0.b.i1", expect: false)
875+
testOverlap("s0.b.i1", "s0.b", expect: false)
876+
testOverlap("s0.b.i1", "s0", expect: true)
850877
}
851878

852879
func testOverlap(_ lhsStr: String, _ rhsStr: String, expect: Bool) {
@@ -889,7 +916,7 @@ extension SmallProjectionPath {
889916
}
890917

891918
func path2path() {
892-
testPath2Path("s0.e2.3.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
919+
testPath2Path("s0.b.e2.3.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
893920
testPath2Path("v**.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
894921
testPath2Path("**", { $0.popAllValueFields() }, expect: "**")
895922

0 commit comments

Comments
 (0)