Merge pull request #84482 from eeckstein/smallprojectionpath-tests

SIL: use `Test` for the SmallProjectionPath's unit tests
This commit is contained in:
eeckstein
2025-09-25 17:37:04 +02:00
committed by GitHub
8 changed files with 309 additions and 332 deletions

View File

@@ -150,7 +150,6 @@ private func registerSwiftPasses() {
registerPass(deadEndBlockDumper, { deadEndBlockDumper.run($0) })
registerPass(memBehaviorDumper, { memBehaviorDumper.run($0) })
registerPass(rangeDumper, { rangeDumper.run($0) })
registerPass(runUnitTests, { runUnitTests.run($0) })
registerPass(testInstructionIteration, { testInstructionIteration.run($0) })
registerPass(updateBorrowedFromPass, { updateBorrowedFromPass.run($0) })
}

View File

@@ -15,7 +15,6 @@ swift_compiler_sources(Optimizer
MemBehaviorDumper.swift
SILPrinter.swift
RangeDumper.swift
RunUnitTests.swift
UpdateBorrowedFrom.swift
TestInstructionIteration.swift
)

View File

@@ -1,24 +0,0 @@
//===--- UnitTests.swift - A pseudo pass for running the unit tests -------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import SIL
/// This pass should only be used by sil-opt to run all the unit tests.
///
let runUnitTests = ModulePass(name: "run-unit-tests") {
(context: ModulePassContext) in
print("--- Run unit tests ---")
print("test ProjectionPath")
SmallProjectionPath.runUnitTests()
}

View File

@@ -680,308 +680,307 @@ extension StringParser {
// Unit Tests
//===----------------------------------------------------------------------===//
extension SmallProjectionPath {
public static func runUnitTests() {
basicPushPop()
parsing()
merging()
subtracting()
matching()
overlapping()
predicates()
path2path()
indexedElements()
let smallProjectionPathTest = Test("small_projection_path") {
function, arguments, context in
func basicPushPop() {
let p1 = SmallProjectionPath(.structField, index: 3)
.push(.classField, index: 12345678)
let (k2, i2, p2) = p1.pop()
assert(k2 == .classField && i2 == 12345678)
let (k3, i3, p3) = p2.pop()
assert(k3 == .structField && i3 == 3)
assert(p3.isEmpty)
let (k4, i4, _) = p2.push(.enumCase, index: 876).pop()
assert(k4 == .enumCase && i4 == 876)
let p5 = SmallProjectionPath(.anything)
assert(p5.pop().path.isEmpty)
let p6 = SmallProjectionPath(.indexedElement, index: 1).push(.indexedElement, index: 2)
let (k6, i6, p7) = p6.pop()
assert(k6 == .indexedElement && i6 == 3 && p7.isEmpty)
let p8 = SmallProjectionPath(.indexedElement, index: 0)
assert(p8.isEmpty)
let p9 = SmallProjectionPath(.indexedElement, index: 1).push(.anyIndexedElement)
let (k9, i9, p10) = p9.pop()
assert(k9 == .anyIndexedElement && i9 == 0 && p10.isEmpty)
let p11 = SmallProjectionPath(.anyIndexedElement).push(.indexedElement, index: 1)
let (k11, i11, p12) = p11.pop()
assert(k11 == .anyIndexedElement && i11 == 0 && p12.isEmpty)
basicPushPop()
parsing()
merging()
subtracting()
matching()
overlapping()
predicates()
path2path()
indexedElements()
func basicPushPop() {
let p1 = SmallProjectionPath(.structField, index: 3)
.push(.classField, index: 12345678)
let (k2, i2, p2) = p1.pop()
assert(k2 == .classField && i2 == 12345678)
let (k3, i3, p3) = p2.pop()
assert(k3 == .structField && i3 == 3)
assert(p3.isEmpty)
let (k4, i4, _) = p2.push(.enumCase, index: 876).pop()
assert(k4 == .enumCase && i4 == 876)
let p5 = SmallProjectionPath(.anything)
assert(p5.pop().path.isEmpty)
let p6 = SmallProjectionPath(.indexedElement, index: 1).push(.indexedElement, index: 2)
let (k6, i6, p7) = p6.pop()
assert(k6 == .indexedElement && i6 == 3 && p7.isEmpty)
let p8 = SmallProjectionPath(.indexedElement, index: 0)
assert(p8.isEmpty)
let p9 = SmallProjectionPath(.indexedElement, index: 1).push(.anyIndexedElement)
let (k9, i9, p10) = p9.pop()
assert(k9 == .anyIndexedElement && i9 == 0 && p10.isEmpty)
let p11 = SmallProjectionPath(.anyIndexedElement).push(.indexedElement, index: 1)
let (k11, i11, p12) = p11.pop()
assert(k11 == .anyIndexedElement && i11 == 0 && p12.isEmpty)
}
func parsing() {
testParse("v**.c*", expect: SmallProjectionPath(.anyClassField)
.push(.anyValueFields))
testParse("s3.c*.v**.s1", expect: SmallProjectionPath(.structField, index: 1)
.push(.anyValueFields)
.push(.anyClassField)
.push(.structField, index: 3))
testParse("2.c*.e6.ct.**", expect: SmallProjectionPath(.anything)
.push(.tailElements)
.push(.enumCase, index: 6)
.push(.anyClassField)
.push(.tupleField, index: 2))
testParse("i3.x.b.i*", expect: SmallProjectionPath(.anyIndexedElement)
.push(.vectorBase)
.push(.existential)
.push(.indexedElement, index: 3))
do {
var parser = StringParser("c*.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.**")
_ = try parser.parseProjectionPathFromSIL()
fatalError("too long path not detected")
} catch {
}
func parsing() {
testParse("v**.c*", expect: SmallProjectionPath(.anyClassField)
.push(.anyValueFields))
testParse("s3.c*.v**.s1", expect: SmallProjectionPath(.structField, index: 1)
.push(.anyValueFields)
.push(.anyClassField)
.push(.structField, index: 3))
testParse("2.c*.e6.ct.**", expect: SmallProjectionPath(.anything)
.push(.tailElements)
.push(.enumCase, index: 6)
.push(.anyClassField)
.push(.tupleField, index: 2))
testParse("i3.x.b.i*", expect: SmallProjectionPath(.anyIndexedElement)
.push(.vectorBase)
.push(.existential)
.push(.indexedElement, index: 3))
do {
var parser = StringParser("c*.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.s123.s3.**")
_ = try parser.parseProjectionPathFromSIL()
fatalError("too long path not detected")
} catch {
}
do {
var parser = StringParser("**.s0")
_ = try parser.parseProjectionPathFromSIL()
fatalError("wrong '**' not detected")
} catch {
}
}
func testParse(_ pathStr: String, expect: SmallProjectionPath) {
var parser = StringParser(pathStr)
let path = try! parser.parseProjectionPathFromSIL()
assert(path == expect)
let str = path.description
assert(str == pathStr)
}
func merging() {
testMerge("c1.c0", "c0", expect: "c*.**")
testMerge("c2.c1", "c2", expect: "c2.**")
testMerge("s3.c0", "v**.c0", expect: "v**.c0")
testMerge("c0", "s2.c1", expect: "v**.c*")
testMerge("s1.s1.c2", "s1.c2", expect: "s1.v**.c2")
testMerge("s1.s0", "s2.s0", expect: "v**")
testMerge("ct", "c2", expect: "c*")
testMerge("i1", "i2", expect: "i*")
testMerge("i*", "i2", expect: "i*")
testMerge("s0.i*.e3", "s0.e3", expect: "s0.i*.e3")
testMerge("i*", "v**", expect: "v**")
testMerge("s0.b.i1", "s0.b.i0", expect: "s0.b.i*")
testMerge("s0.b", "s0.1", expect: "s0.v**")
testMerge("ct.s0.e0.v**.c0", "ct.s0.e0.v**.c0", expect: "ct.s0.e0.v**.c0")
testMerge("ct.s0.s0.c0", "ct.s0.e0.s0.c0", expect: "ct.s0.v**.c0")
}
func testMerge(_ lhsStr: String, _ rhsStr: String,
expect expectStr: String) {
var lhsParser = StringParser(lhsStr)
let lhs = try! lhsParser.parseProjectionPathFromSIL()
var rhsParser = StringParser(rhsStr)
let rhs = try! rhsParser.parseProjectionPathFromSIL()
var expectParser = StringParser(expectStr)
let expect = try! expectParser.parseProjectionPathFromSIL()
let result = lhs.merge(with: rhs)
assert(result == expect)
let result2 = rhs.merge(with: lhs)
assert(result2 == expect)
}
func subtracting() {
testSubtract("s0", "s0.s1", expect: "s1")
testSubtract("s0", "s1", expect: nil)
testSubtract("s0.s1", "s0.s1", expect: "")
testSubtract("i*.s1", "i*.s1", expect: nil)
testSubtract("ct.s1.0.i3.x", "ct.s1.0.i3.x", expect: "")
testSubtract("c0.s1.0.i3", "c0.s1.0.i3.x", expect: "x")
testSubtract("s1.0.i3.x", "s1.0.i3", expect: nil)
testSubtract("v**.s1", "v**.s1", expect: nil)
testSubtract("i*", "i*", expect: nil)
}
func testSubtract(_ lhsStr: String, _ rhsStr: String, expect expectStr: String?) {
var lhsParser = StringParser(lhsStr)
let lhs = try! lhsParser.parseProjectionPathFromSIL()
var rhsParser = StringParser(rhsStr)
let rhs = try! rhsParser.parseProjectionPathFromSIL()
let result = lhs.subtract(from: rhs)
if let expectStr = expectStr {
var expectParser = StringParser(expectStr)
let expect = try! expectParser.parseProjectionPathFromSIL()
assert(result! == expect)
} else {
assert(result == nil)
}
}
func matching() {
testMatch("ct", "c*", expect: true)
testMatch("c1", "c*", expect: true)
testMatch("s2", "v**", expect: true)
testMatch("1", "v**", expect: true)
testMatch("e1", "v**", expect: true)
testMatch("c*", "c1", expect: false)
testMatch("c*", "ct", expect: false)
testMatch("v**", "s0", expect: false)
testMatch("i1", "i1", expect: true)
testMatch("i1", "i*", expect: true)
testMatch("i*", "i1", expect: false)
testMatch("s0.s1", "s0.s1", expect: true)
testMatch("s0.s2", "s0.s1", expect: false)
testMatch("s0", "s0.v**", expect: true)
testMatch("s0.s1", "s0.v**", expect: true)
testMatch("s0.1.e2", "s0.v**", expect: true)
testMatch("s0.v**.x.e2", "v**", expect: true)
testMatch("s0.v**", "s0.s1", expect: false)
testMatch("s0.s1.c*", "s0.v**", expect: false)
testMatch("s0.v**", "s0.**", expect: true)
testMatch("s1.v**", "s0.**", expect: false)
testMatch("s0.**", "s0.v**", expect: false)
testMatch("s0.s1", "s0.i*.s1", expect: true)
testMatch("s0.b.s1", "s0.b.i*.s1", expect: true)
}
func testMatch(_ lhsStr: String, _ rhsStr: String, expect: Bool) {
var lhsParser = StringParser(lhsStr)
let lhs = try! lhsParser.parseProjectionPathFromSIL()
var rhsParser = StringParser(rhsStr)
let rhs = try! rhsParser.parseProjectionPathFromSIL()
let result = lhs.matches(pattern: rhs)
assert(result == expect)
}
func overlapping() {
testOverlap("s0.s1.s2", "s0.s1.s2", expect: true)
testOverlap("s0.s1.s2", "s0.s2.s2", expect: false)
testOverlap("s0.s1.s2", "s0.e1.s2", expect: false)
testOverlap("s0.s1.s2", "s0.s1", expect: true)
testOverlap("s0.s1.s2", "s1.s2", expect: false)
testOverlap("s0.c*.s2", "s0.ct.s2", expect: true)
testOverlap("s0.c*.s2", "s0.c1.s2", expect: true)
testOverlap("s0.c*.s2", "s0.c1.c2.s2", expect: false)
testOverlap("s0.c*.s2", "s0.s2", expect: false)
testOverlap("s0.v**.s2", "s0.s3.x", expect: true)
testOverlap("s0.v**.s2.c2", "s0.s3.c1", expect: false)
testOverlap("s0.v**.s2", "s1.s3", expect: false)
testOverlap("s0.v**.s2", "s0.v**.s3", expect: true)
testOverlap("s0.**", "s0.s3.c1", expect: true)
testOverlap("**", "s0.s3.c1", expect: true)
testOverlap("i1", "i*", expect: true)
testOverlap("i1", "v**", expect: true)
testOverlap("s0.i*.s1", "s0.s1", expect: true)
testOverlap("s0.b.s1", "s0.b.i*.s1", expect: true)
testOverlap("s0.b.i0.s1", "s0.b.i1.s1", expect: false)
testOverlap("s0.b.i2.s1", "s0.b.i1.s1", expect: false)
testOverlap("s0.b.s1", "s0.b.i0.s1", expect: true)
testOverlap("s0.b", "s0.b.i1", expect: false)
testOverlap("s0.b.i1", "s0.b", expect: false)
testOverlap("s0.b.i1", "s0", expect: true)
}
func testOverlap(_ lhsStr: String, _ rhsStr: String, expect: Bool) {
var lhsParser = StringParser(lhsStr)
let lhs = try! lhsParser.parseProjectionPathFromSIL()
var rhsParser = StringParser(rhsStr)
let rhs = try! rhsParser.parseProjectionPathFromSIL()
let result = lhs.mayOverlap(with: rhs)
assert(result == expect)
let reversedResult = rhs.mayOverlap(with: lhs)
assert(reversedResult == expect)
}
func predicates() {
testPredicate("v**", \.hasClassProjection, expect: false)
testPredicate("v**.c0.s1.v**", \.hasClassProjection, expect: true)
testPredicate("c0.**", \.hasClassProjection, expect: true)
testPredicate("c0.c1", \.hasClassProjection, expect: true)
testPredicate("ct", \.hasClassProjection, expect: true)
testPredicate("s0", \.hasClassProjection, expect: false)
testPredicate("v**", \.mayHaveClassProjection, expect: false)
testPredicate("c0", \.mayHaveClassProjection, expect: true)
testPredicate("1", \.mayHaveClassProjection, expect: false)
testPredicate("**", \.mayHaveClassProjection, expect: true)
testPredicate("v**", \.mayHaveTwoClassProjections, expect: false)
testPredicate("c0", \.mayHaveTwoClassProjections, expect: false)
testPredicate("**", \.mayHaveTwoClassProjections, expect: true)
testPredicate("v**.c*.s2.1.c0", \.mayHaveTwoClassProjections, expect: true)
testPredicate("c*.s2.1.c0.v**", \.mayHaveTwoClassProjections, expect: true)
testPredicate("v**.c*.**", \.mayHaveTwoClassProjections, expect: true)
}
func testPredicate(_ pathStr: String, _ property: (SmallProjectionPath) -> Bool, expect: Bool) {
var parser = StringParser(pathStr)
let path = try! parser.parseProjectionPathFromSIL()
let result = property(path)
assert(result == expect)
}
func path2path() {
testPath2Path("s0.b.e2.3.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
testPath2Path("v**.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
testPath2Path("**", { $0.popAllValueFields() }, expect: "**")
testPath2Path("s0.e2.3.c4.s1.e2.v**.**", { $0.popLastClassAndValuesFromTail() }, expect: "s0.e2.3.c4.s1.e2.v**.**")
testPath2Path("s0.c2.3.c4.s1", { $0.popLastClassAndValuesFromTail() }, expect: "s0.c2.3")
testPath2Path("v**.c*.s1", { $0.popLastClassAndValuesFromTail() }, expect: "v**")
testPath2Path("s1.ct.v**", { $0.popLastClassAndValuesFromTail() }, expect: "s1")
testPath2Path("c0.c1.c2", { $0.popLastClassAndValuesFromTail() }, expect: "c0.c1")
testPath2Path("**", { $0.popLastClassAndValuesFromTail() }, expect: "**")
testPath2Path("v**.c3", { $0.popIfMatches(.anyValueFields) }, expect: "v**.c3")
testPath2Path("**", { $0.popIfMatches(.anyValueFields) }, expect: "**")
testPath2Path("s0.c3", { $0.popIfMatches(.anyValueFields) }, expect: nil)
testPath2Path("c0.s3", { $0.popIfMatches(.anyClassField) }, expect: nil)
testPath2Path("**", { $0.popIfMatches(.anyClassField) }, expect: "**")
testPath2Path("c*.e3", { $0.popIfMatches(.anyClassField) }, expect: "e3")
testPath2Path("i*.e3.s0", { $0.popIfMatches(.enumCase, index: 3) }, expect: "s0")
testPath2Path("i1.e3.s0", { $0.popIfMatches(.enumCase, index: 3) }, expect: nil)
testPath2Path("i*.e3.s0", { $0.popIfMatches(.indexedElement, index: 0) }, expect: "i*.e3.s0")
}
func testPath2Path(_ pathStr: String, _ transform: (SmallProjectionPath) -> SmallProjectionPath?, expect: String?) {
var parser = StringParser(pathStr)
let path = try! parser.parseProjectionPathFromSIL()
let result = transform(path)
if let expect = expect {
var expectParser = StringParser(expect)
let expectPath = try! expectParser.parseProjectionPathFromSIL()
assert(result == expectPath)
} else {
assert(result == nil)
}
}
func indexedElements() {
let p1 = SmallProjectionPath(.indexedElement, index: 1)
let (k1, i1, s1) = p1.pop()
assert(k1 == .indexedElement && i1 == 1 && s1.isEmpty)
let p2 = SmallProjectionPath(.indexedElement, index: -1)
let (k2, _, s2) = p2.pop()
assert(k2 == .anything && s2.isEmpty)
let p3 = SmallProjectionPath(.indexedElement, index: 0xfffffffffffff)
let (k3, i3, s3) = p3.pop()
assert(k3 == .indexedElement && i3 == 0xfffffffffffff && s3.isEmpty)
let p4 = p3.push(.indexedElement, index: Int.max)
let (k4, _, s4) = p4.pop()
assert(k4 == .anyIndexedElement && s4.isEmpty)
do {
var parser = StringParser("**.s0")
_ = try parser.parseProjectionPathFromSIL()
fatalError("wrong '**' not detected")
} catch {
}
}
func testParse(_ pathStr: String, expect: SmallProjectionPath) {
var parser = StringParser(pathStr)
let path = try! parser.parseProjectionPathFromSIL()
assert(path == expect)
let str = path.description
assert(str == pathStr)
}
func merging() {
testMerge("c1.c0", "c0", expect: "c*.**")
testMerge("c2.c1", "c2", expect: "c2.**")
testMerge("s3.c0", "v**.c0", expect: "v**.c0")
testMerge("c0", "s2.c1", expect: "v**.c*")
testMerge("s1.s1.c2", "s1.c2", expect: "s1.v**.c2")
testMerge("s1.s0", "s2.s0", expect: "v**")
testMerge("ct", "c2", expect: "c*")
testMerge("i1", "i2", expect: "i*")
testMerge("i*", "i2", expect: "i*")
testMerge("s0.i*.e3", "s0.e3", expect: "s0.i*.e3")
testMerge("i*", "v**", expect: "v**")
testMerge("s0.b.i1", "s0.b.i0", expect: "s0.b.i*")
testMerge("s0.b", "s0.1", expect: "s0.v**")
testMerge("ct.s0.e0.v**.c0", "ct.s0.e0.v**.c0", expect: "ct.s0.e0.v**.c0")
testMerge("ct.s0.s0.c0", "ct.s0.e0.s0.c0", expect: "ct.s0.v**.c0")
}
func testMerge(_ lhsStr: String, _ rhsStr: String,
expect expectStr: String) {
var lhsParser = StringParser(lhsStr)
let lhs = try! lhsParser.parseProjectionPathFromSIL()
var rhsParser = StringParser(rhsStr)
let rhs = try! rhsParser.parseProjectionPathFromSIL()
var expectParser = StringParser(expectStr)
let expect = try! expectParser.parseProjectionPathFromSIL()
let result = lhs.merge(with: rhs)
assert(result == expect)
let result2 = rhs.merge(with: lhs)
assert(result2 == expect)
}
func subtracting() {
testSubtract("s0", "s0.s1", expect: "s1")
testSubtract("s0", "s1", expect: nil)
testSubtract("s0.s1", "s0.s1", expect: "")
testSubtract("i*.s1", "i*.s1", expect: nil)
testSubtract("ct.s1.0.i3.x", "ct.s1.0.i3.x", expect: "")
testSubtract("c0.s1.0.i3", "c0.s1.0.i3.x", expect: "x")
testSubtract("s1.0.i3.x", "s1.0.i3", expect: nil)
testSubtract("v**.s1", "v**.s1", expect: nil)
testSubtract("i*", "i*", expect: nil)
}
func testSubtract(_ lhsStr: String, _ rhsStr: String, expect expectStr: String?) {
var lhsParser = StringParser(lhsStr)
let lhs = try! lhsParser.parseProjectionPathFromSIL()
var rhsParser = StringParser(rhsStr)
let rhs = try! rhsParser.parseProjectionPathFromSIL()
let result = lhs.subtract(from: rhs)
if let expectStr = expectStr {
var expectParser = StringParser(expectStr)
let expect = try! expectParser.parseProjectionPathFromSIL()
assert(result! == expect)
} else {
assert(result == nil)
}
}
func matching() {
testMatch("ct", "c*", expect: true)
testMatch("c1", "c*", expect: true)
testMatch("s2", "v**", expect: true)
testMatch("1", "v**", expect: true)
testMatch("e1", "v**", expect: true)
testMatch("c*", "c1", expect: false)
testMatch("c*", "ct", expect: false)
testMatch("v**", "s0", expect: false)
testMatch("i1", "i1", expect: true)
testMatch("i1", "i*", expect: true)
testMatch("i*", "i1", expect: false)
testMatch("s0.s1", "s0.s1", expect: true)
testMatch("s0.s2", "s0.s1", expect: false)
testMatch("s0", "s0.v**", expect: true)
testMatch("s0.s1", "s0.v**", expect: true)
testMatch("s0.1.e2", "s0.v**", expect: true)
testMatch("s0.v**.x.e2", "v**", expect: true)
testMatch("s0.v**", "s0.s1", expect: false)
testMatch("s0.s1.c*", "s0.v**", expect: false)
testMatch("s0.v**", "s0.**", expect: true)
testMatch("s1.v**", "s0.**", expect: false)
testMatch("s0.**", "s0.v**", expect: false)
testMatch("s0.s1", "s0.i*.s1", expect: true)
testMatch("s0.b.s1", "s0.b.i*.s1", expect: true)
}
func testMatch(_ lhsStr: String, _ rhsStr: String, expect: Bool) {
var lhsParser = StringParser(lhsStr)
let lhs = try! lhsParser.parseProjectionPathFromSIL()
var rhsParser = StringParser(rhsStr)
let rhs = try! rhsParser.parseProjectionPathFromSIL()
let result = lhs.matches(pattern: rhs)
assert(result == expect)
}
func overlapping() {
testOverlap("s0.s1.s2", "s0.s1.s2", expect: true)
testOverlap("s0.s1.s2", "s0.s2.s2", expect: false)
testOverlap("s0.s1.s2", "s0.e1.s2", expect: false)
testOverlap("s0.s1.s2", "s0.s1", expect: true)
testOverlap("s0.s1.s2", "s1.s2", expect: false)
testOverlap("s0.c*.s2", "s0.ct.s2", expect: true)
testOverlap("s0.c*.s2", "s0.c1.s2", expect: true)
testOverlap("s0.c*.s2", "s0.c1.c2.s2", expect: false)
testOverlap("s0.c*.s2", "s0.s2", expect: false)
testOverlap("s0.v**.s2", "s0.s3.x", expect: true)
testOverlap("s0.v**.s2.c2", "s0.s3.c1", expect: false)
testOverlap("s0.v**.s2", "s1.s3", expect: false)
testOverlap("s0.v**.s2", "s0.v**.s3", expect: true)
testOverlap("s0.**", "s0.s3.c1", expect: true)
testOverlap("**", "s0.s3.c1", expect: true)
testOverlap("i1", "i*", expect: true)
testOverlap("i1", "v**", expect: true)
testOverlap("s0.i*.s1", "s0.s1", expect: true)
testOverlap("s0.b.s1", "s0.b.i*.s1", expect: true)
testOverlap("s0.b.i0.s1", "s0.b.i1.s1", expect: false)
testOverlap("s0.b.i2.s1", "s0.b.i1.s1", expect: false)
testOverlap("s0.b.s1", "s0.b.i0.s1", expect: true)
testOverlap("s0.b", "s0.b.i1", expect: false)
testOverlap("s0.b.i1", "s0.b", expect: false)
testOverlap("s0.b.i1", "s0", expect: true)
}
func testOverlap(_ lhsStr: String, _ rhsStr: String, expect: Bool) {
var lhsParser = StringParser(lhsStr)
let lhs = try! lhsParser.parseProjectionPathFromSIL()
var rhsParser = StringParser(rhsStr)
let rhs = try! rhsParser.parseProjectionPathFromSIL()
let result = lhs.mayOverlap(with: rhs)
assert(result == expect)
let reversedResult = rhs.mayOverlap(with: lhs)
assert(reversedResult == expect)
}
func predicates() {
testPredicate("v**", \.hasClassProjection, expect: false)
testPredicate("v**.c0.s1.v**", \.hasClassProjection, expect: true)
testPredicate("c0.**", \.hasClassProjection, expect: true)
testPredicate("c0.c1", \.hasClassProjection, expect: true)
testPredicate("ct", \.hasClassProjection, expect: true)
testPredicate("s0", \.hasClassProjection, expect: false)
testPredicate("v**", \.mayHaveClassProjection, expect: false)
testPredicate("c0", \.mayHaveClassProjection, expect: true)
testPredicate("1", \.mayHaveClassProjection, expect: false)
testPredicate("**", \.mayHaveClassProjection, expect: true)
testPredicate("v**", \.mayHaveTwoClassProjections, expect: false)
testPredicate("c0", \.mayHaveTwoClassProjections, expect: false)
testPredicate("**", \.mayHaveTwoClassProjections, expect: true)
testPredicate("v**.c*.s2.1.c0", \.mayHaveTwoClassProjections, expect: true)
testPredicate("c*.s2.1.c0.v**", \.mayHaveTwoClassProjections, expect: true)
testPredicate("v**.c*.**", \.mayHaveTwoClassProjections, expect: true)
}
func testPredicate(_ pathStr: String, _ property: (SmallProjectionPath) -> Bool, expect: Bool) {
var parser = StringParser(pathStr)
let path = try! parser.parseProjectionPathFromSIL()
let result = property(path)
assert(result == expect)
}
func path2path() {
testPath2Path("s0.b.e2.3.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
testPath2Path("v**.c4.s1", { $0.popAllValueFields() }, expect: "c4.s1")
testPath2Path("**", { $0.popAllValueFields() }, expect: "**")
testPath2Path("s0.e2.3.c4.s1.e2.v**.**", { $0.popLastClassAndValuesFromTail() }, expect: "s0.e2.3.c4.s1.e2.v**.**")
testPath2Path("s0.c2.3.c4.s1", { $0.popLastClassAndValuesFromTail() }, expect: "s0.c2.3")
testPath2Path("v**.c*.s1", { $0.popLastClassAndValuesFromTail() }, expect: "v**")
testPath2Path("s1.ct.v**", { $0.popLastClassAndValuesFromTail() }, expect: "s1")
testPath2Path("c0.c1.c2", { $0.popLastClassAndValuesFromTail() }, expect: "c0.c1")
testPath2Path("**", { $0.popLastClassAndValuesFromTail() }, expect: "**")
testPath2Path("v**.c3", { $0.popIfMatches(.anyValueFields) }, expect: "v**.c3")
testPath2Path("**", { $0.popIfMatches(.anyValueFields) }, expect: "**")
testPath2Path("s0.c3", { $0.popIfMatches(.anyValueFields) }, expect: nil)
testPath2Path("c0.s3", { $0.popIfMatches(.anyClassField) }, expect: nil)
testPath2Path("**", { $0.popIfMatches(.anyClassField) }, expect: "**")
testPath2Path("c*.e3", { $0.popIfMatches(.anyClassField) }, expect: "e3")
testPath2Path("i*.e3.s0", { $0.popIfMatches(.enumCase, index: 3) }, expect: "s0")
testPath2Path("i1.e3.s0", { $0.popIfMatches(.enumCase, index: 3) }, expect: nil)
testPath2Path("i*.e3.s0", { $0.popIfMatches(.indexedElement, index: 0) }, expect: "i*.e3.s0")
}
func testPath2Path(_ pathStr: String, _ transform: (SmallProjectionPath) -> SmallProjectionPath?, expect: String?) {
var parser = StringParser(pathStr)
let path = try! parser.parseProjectionPathFromSIL()
let result = transform(path)
if let expect = expect {
var expectParser = StringParser(expect)
let expectPath = try! expectParser.parseProjectionPathFromSIL()
assert(result == expectPath)
} else {
assert(result == nil)
}
}
func indexedElements() {
let p1 = SmallProjectionPath(.indexedElement, index: 1)
let (k1, i1, s1) = p1.pop()
assert(k1 == .indexedElement && i1 == 1 && s1.isEmpty)
let p2 = SmallProjectionPath(.indexedElement, index: -1)
let (k2, _, s2) = p2.pop()
assert(k2 == .anything && s2.isEmpty)
let p3 = SmallProjectionPath(.indexedElement, index: 0xfffffffffffff)
let (k3, i3, s3) = p3.pop()
assert(k3 == .indexedElement && i3 == 0xfffffffffffff && s3.isEmpty)
let p4 = p3.push(.indexedElement, index: Int.max)
let (k4, _, s4) = p4.pop()
assert(k4 == .anyIndexedElement && s4.isEmpty)
}
}

View File

@@ -142,6 +142,7 @@ public func registerTests() {
// Register each test.
registerTests(
parseTestSpecificationTest,
smallProjectionPathTest,
getAccessBaseTest,
borrowIntroducersTest,
enclosingValuesTest,

View File

@@ -163,8 +163,6 @@ MODULE_PASS(MandatoryAllocBoxToStack, "mandatory-allocbox-to-stack",
"Mandatory stack promotion of box objects")
MODULE_PASS(AsyncDemotion, "async-demotion",
"Convert async functions to be synchronous")
MODULE_PASS(RunUnitTests, "run-unit-tests",
"Runs the compiler internal unit tests")
MODULE_PASS(FunctionUsesDumper, "dump-function-uses",
"Dump the results of FunctionUses")
MODULE_PASS(MandatoryPerformanceOptimizations, "mandatory-performance-optimizations",

View File

@@ -0,0 +1,9 @@
// RUN: %target-sil-opt -test-runner -sil-disable-input-verify %s -o /dev/null
sil_stage raw
sil @small_projection_path_unit_tests : $@convention(thin) () -> () {
bb0:
specify_test "small_projection_path"
unreachable
}

View File

@@ -1,4 +0,0 @@
// RUN: %target-sil-opt %s -run-unit-tests -o /dev/null
// REQUIRES: swift_in_compiler