Skip to content

Commit e4219c9

Browse files
committed
Implement normalizing of Windows triples, other edge cases based on LLVM.
1 parent 59d018b commit e4219c9

File tree

2 files changed

+143
-58
lines changed

2 files changed

+143
-58
lines changed

Sources/SwiftDriver/Utilities/Triple.swift

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,21 +98,64 @@ public struct Triple {
9898
var parsedOS = parser.match(OS.self, at: 2)
9999
var parsedEnv = parser.match(EnvInfo.self, at: 3)
100100

101+
var isCygwin = parser.componentsIndicateCygwin
102+
var isMinGW32 = parser.componentsIndicateMinGW32
103+
101104
if normalizing {
102105
// Next, try to fill in each unmatched field from the rejected components.
103106
parser.rematch(&parsedArch, at: 0)
104107
parser.rematch(&parsedVendor, at: 1)
105108
parser.rematch(&parsedOS, at: 2)
106109
parser.rematch(&parsedEnv, at: 3)
107110

108-
// TODO: This normalization logic is a little less robust than LLVM's.
109-
// In particular, it doesn't correct Windows triples as well as
110-
// llvm::Triple::normalize() does.
111+
isCygwin = parser.componentsIndicateCygwin
112+
isMinGW32 = parser.componentsIndicateMinGW32
113+
114+
if
115+
let parsedEnv = parsedEnv,
116+
let environment = parsedEnv.value.environment,
117+
environment == .android,
118+
parsedEnv.substring.starts(with: "androideabi") {
119+
let androidVersion = parsedEnv.substring.dropFirst("androideabi".count)
120+
121+
parser.components[3] = "android\(androidVersion)"
122+
}
123+
124+
// SUSE uses "gnueabi" to mean "gnueabihf"
125+
if parsedVendor?.value == .suse && parsedEnv?.value.environment == .gnueabi {
126+
parser.components[3] = "gnueabihf"
127+
}
128+
129+
if parsedOS?.value == .win32 {
130+
parser.components.resize(toCount: 4, paddingWith: "")
131+
parser.components[2] = "windows"
132+
if parsedEnv?.value.environment == nil {
133+
if let objectFormat = parsedEnv?.value.objectFormat, objectFormat != .coff {
134+
parser.components[3] = Substring(objectFormat.name)
135+
} else {
136+
parser.components[3] = "msvc"
137+
}
138+
}
139+
} else if isMinGW32 {
140+
parser.components.resize(toCount: 4, paddingWith: "")
141+
parser.components[2] = "windows"
142+
parser.components[3] = "gnu"
143+
} else if isCygwin {
144+
parser.components.resize(toCount: 4, paddingWith: "")
145+
parser.components[2] = "windows"
146+
parser.components[3] = "cygnus"
147+
}
148+
149+
if isMinGW32 || isCygwin || (parsedOS?.value == .win32 && parsedEnv?.value.environment != nil) {
150+
if let objectFormat = parsedEnv?.value.objectFormat, objectFormat != .coff {
151+
parser.components.resize(toCount: 5, paddingWith: "")
152+
parser.components[4] = Substring(objectFormat.name)
153+
}
154+
}
111155

112156
// Now that we've parsed everything, we construct a normalized form of the
113157
// triple string.
114-
triple = parser.components.map { $0 == "" ? "unknown" : $0 }
115-
.joined(separator: "-")
158+
triple = parser.components.map({ $0.isEmpty ? "unknown" : $0 }).joined(separator: "-")
116159
}
117160
else {
118161
triple = string
@@ -141,6 +184,14 @@ public struct Triple {
141184

142185
fileprivate protocol TripleComponent {
143186
static func parse(_ component: Substring) -> Self?
187+
188+
static func valueIsValid(_ value: Substring) -> Bool
189+
}
190+
191+
extension TripleComponent {
192+
static func valueIsValid(_ value: Substring) -> Bool {
193+
parse(value) != nil
194+
}
144195
}
145196

146197
fileprivate struct ParsedComponent<Value: TripleComponent> {
@@ -178,6 +229,14 @@ fileprivate struct TripleParser {
178229
var components: [Substring]
179230
var isMatched: Set<Int> = []
180231

232+
var componentsIndicateCygwin: Bool {
233+
components.count > 2 ? components[2].starts(with: "cygwin") : false
234+
}
235+
236+
var componentsIndicateMinGW32: Bool {
237+
components.count > 2 ? components[2].starts(with: "mingw") : false
238+
}
239+
181240
init(_ string: String, allowMore: Bool) {
182241
components = string.split(
183242
separator: "-", maxSplits: allowMore ? Int.max : 3,
@@ -214,11 +273,11 @@ fileprivate struct TripleParser {
214273
"Lost the parsed component somehow?")
215274

216275
for i in unmatchedIndices {
217-
guard let parsed = ParsedComponent(components[i], as: Value.self) else {
276+
guard Value.valueIsValid(components[i]) else {
218277
continue
219278
}
220279

221-
value = parsed
280+
value = ParsedComponent(components[i], as: Value.self)
222281
shiftComponent(at: i, to: correctIndex)
223282
isMatched.insert(correctIndex)
224283

@@ -1120,6 +1179,10 @@ extension Triple {
11201179
return nil
11211180
}
11221181
}
1182+
1183+
fileprivate static func valueIsValid(_ value: Substring) -> Bool {
1184+
parse(value) != nil || value.starts(with: "cygwin") || value.starts(with: "mingw")
1185+
}
11231186
}
11241187
}
11251188

@@ -1361,6 +1424,16 @@ extension Triple {
13611424
return .wasm
13621425
}
13631426
}
1427+
1428+
var name: String {
1429+
switch self {
1430+
case .coff: return "coff"
1431+
case .elf: return "elf"
1432+
case .macho: return "macho"
1433+
case .wasm: return "wasm"
1434+
case .xcoff: return "xcoff"
1435+
}
1436+
}
13641437
}
13651438
}
13661439

@@ -1558,3 +1631,15 @@ extension Triple {
15581631
}
15591632
}
15601633
}
1634+
1635+
extension Array {
1636+
1637+
mutating func resize(toCount desiredCount: Int, paddingWith element: Element) {
1638+
1639+
if desiredCount > count {
1640+
append(contentsOf: repeatElement(element, count: desiredCount - count))
1641+
} else if desiredCount < count {
1642+
removeLast(count - desiredCount)
1643+
}
1644+
}
1645+
}

Tests/SwiftDriverTests/TripleTests.swift

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -712,8 +712,8 @@ final class TripleTests: XCTestCase {
712712
func testNormalizeSpecialCases() {
713713
// Various real-world funky triples. The value returned by GCC's config.sub
714714
// is given in the comment.
715-
// assertNormalizesEqual("i386-mingw32",
716-
// "i386-unknown-windows-gnu") // i386-pc-mingw32
715+
assertNormalizesEqual("i386-mingw32",
716+
"i386-unknown-windows-gnu") // i386-pc-mingw32
717717
assertNormalizesEqual("x86_64-linux-gnu",
718718
"x86_64-unknown-linux-gnu") // x86_64-pc-linux-gnu
719719
assertNormalizesEqual("i486-linux-gnu",
@@ -731,37 +731,37 @@ final class TripleTests: XCTestCase {
731731
}
732732

733733
func testNormalizeWindows() {
734-
// assertNormalizesEqual("i686-pc-win32", "i686-pc-windows-msvc")
735-
// assertNormalizesEqual("i686-win32", "i686-unknown-windows-msvc")
736-
// assertNormalizesEqual("i686-pc-mingw32", "i686-pc-windows-gnu")
737-
// assertNormalizesEqual("i686-mingw32", "i686-unknown-windows-gnu")
738-
// assertNormalizesEqual("i686-pc-mingw32-w64", "i686-pc-windows-gnu")
739-
// assertNormalizesEqual("i686-mingw32-w64", "i686-unknown-windows-gnu")
740-
// assertNormalizesEqual("i686-pc-cygwin", "i686-pc-windows-cygnus")
741-
// assertNormalizesEqual("i686-cygwin", "i686-unknown-windows-cygnus")
742-
//
743-
// assertNormalizesEqual("x86_64-pc-win32", "x86_64-pc-windows-msvc")
744-
// assertNormalizesEqual("x86_64-win32", "x86_64-unknown-windows-msvc")
745-
// assertNormalizesEqual("x86_64-pc-mingw32", "x86_64-pc-windows-gnu")
746-
// assertNormalizesEqual("x86_64-mingw32", "x86_64-unknown-windows-gnu")
747-
// assertNormalizesEqual("x86_64-pc-mingw32-w64",
748-
// "x86_64-pc-windows-gnu")
749-
// assertNormalizesEqual("x86_64-mingw32-w64",
750-
// "x86_64-unknown-windows-gnu")
751-
//
752-
// assertNormalizesEqual("i686-pc-win32-elf", "i686-pc-windows-elf")
753-
// assertNormalizesEqual("i686-win32-elf", "i686-unknown-windows-elf")
754-
// assertNormalizesEqual("i686-pc-win32-macho", "i686-pc-windows-macho")
755-
// assertNormalizesEqual("i686-win32-macho",
756-
// "i686-unknown-windows-macho")
757-
//
758-
// assertNormalizesEqual("x86_64-pc-win32-elf", "x86_64-pc-windows-elf")
759-
// assertNormalizesEqual("x86_64-win32-elf",
760-
// "x86_64-unknown-windows-elf")
761-
// assertNormalizesEqual("x86_64-pc-win32-macho",
762-
// "x86_64-pc-windows-macho")
763-
// assertNormalizesEqual("x86_64-win32-macho",
764-
// "x86_64-unknown-windows-macho")
734+
assertNormalizesEqual("i686-pc-win32", "i686-pc-windows-msvc")
735+
assertNormalizesEqual("i686-win32", "i686-unknown-windows-msvc")
736+
assertNormalizesEqual("i686-pc-mingw32", "i686-pc-windows-gnu")
737+
assertNormalizesEqual("i686-mingw32", "i686-unknown-windows-gnu")
738+
assertNormalizesEqual("i686-pc-mingw32-w64", "i686-pc-windows-gnu")
739+
assertNormalizesEqual("i686-mingw32-w64", "i686-unknown-windows-gnu")
740+
assertNormalizesEqual("i686-pc-cygwin", "i686-pc-windows-cygnus")
741+
assertNormalizesEqual("i686-cygwin", "i686-unknown-windows-cygnus")
742+
743+
assertNormalizesEqual("x86_64-pc-win32", "x86_64-pc-windows-msvc")
744+
assertNormalizesEqual("x86_64-win32", "x86_64-unknown-windows-msvc")
745+
assertNormalizesEqual("x86_64-pc-mingw32", "x86_64-pc-windows-gnu")
746+
assertNormalizesEqual("x86_64-mingw32", "x86_64-unknown-windows-gnu")
747+
assertNormalizesEqual("x86_64-pc-mingw32-w64",
748+
"x86_64-pc-windows-gnu")
749+
assertNormalizesEqual("x86_64-mingw32-w64",
750+
"x86_64-unknown-windows-gnu")
751+
752+
assertNormalizesEqual("i686-pc-win32-elf", "i686-pc-windows-elf")
753+
assertNormalizesEqual("i686-win32-elf", "i686-unknown-windows-elf")
754+
assertNormalizesEqual("i686-pc-win32-macho", "i686-pc-windows-macho")
755+
assertNormalizesEqual("i686-win32-macho",
756+
"i686-unknown-windows-macho")
757+
758+
assertNormalizesEqual("x86_64-pc-win32-elf", "x86_64-pc-windows-elf")
759+
assertNormalizesEqual("x86_64-win32-elf",
760+
"x86_64-unknown-windows-elf")
761+
assertNormalizesEqual("x86_64-pc-win32-macho",
762+
"x86_64-pc-windows-macho")
763+
assertNormalizesEqual("x86_64-win32-macho",
764+
"x86_64-unknown-windows-macho")
765765

766766
assertNormalizesEqual("i686-pc-windows-cygnus",
767767
"i686-pc-windows-cygnus")
@@ -770,8 +770,8 @@ final class TripleTests: XCTestCase {
770770
"i686-pc-windows-itanium")
771771
assertNormalizesEqual("i686-pc-windows-msvc", "i686-pc-windows-msvc")
772772

773-
// assertNormalizesEqual("i686-pc-windows-elf-elf",
774-
// "i686-pc-windows-elf")
773+
assertNormalizesEqual("i686-pc-windows-elf-elf",
774+
"i686-pc-windows-elf")
775775
}
776776

777777
func testNormalizeARM() {
@@ -792,8 +792,8 @@ final class TripleTests: XCTestCase {
792792
assertNormalizesEqual("armv7eb-netbsd-eabihf",
793793
"armv7eb-unknown-netbsd-eabihf")
794794

795-
// assertNormalizesEqual("armv7-suse-linux-gnueabi",
796-
// "armv7-suse-linux-gnueabihf")
795+
assertNormalizesEqual("armv7-suse-linux-gnueabi",
796+
"armv7-suse-linux-gnueabihf")
797797

798798
var T: Triple
799799
T = Triple("armv6--netbsd-eabi")
@@ -815,9 +815,9 @@ final class TripleTests: XCTestCase {
815815
T = Triple("i386-apple-darwin9")
816816
XCTAssertTrue(T.os?.isMacOSX)
817817
XCTAssertFalse(T.os?.isiOS)
818-
// XCTAssertFalse(T.isArch16Bit())
819-
// XCTAssertTrue(T.isArch32Bit())
820-
// XCTAssertFalse(T.isArch64Bit())
818+
XCTAssertFalse(T.arch?.is16Bit)
819+
XCTAssertTrue(T.arch?.is32Bit)
820+
XCTAssertFalse(T.arch?.is64Bit)
821821
V = T._macOSVersion
822822
XCTAssertEqual(V?.major, 10)
823823
XCTAssertEqual(V?.minor, 5)
@@ -830,9 +830,9 @@ final class TripleTests: XCTestCase {
830830
T = Triple("x86_64-apple-darwin9")
831831
XCTAssertTrue(T.os?.isMacOSX)
832832
XCTAssertFalse(T.os?.isiOS)
833-
// XCTAssertFalse(T.isArch16Bit())
834-
// XCTAssertFalse(T.isArch32Bit())
835-
// XCTAssertTrue(T.isArch64Bit())
833+
XCTAssertFalse(T.arch?.is16Bit)
834+
XCTAssertFalse(T.arch?.is32Bit)
835+
XCTAssertTrue(T.arch?.is64Bit)
836836
V = T._macOSVersion
837837
XCTAssertEqual(V?.major, 10)
838838
XCTAssertEqual(V?.minor, 5)
@@ -845,9 +845,9 @@ final class TripleTests: XCTestCase {
845845
T = Triple("x86_64-apple-macosx")
846846
XCTAssertTrue(T.os?.isMacOSX)
847847
XCTAssertFalse(T.os?.isiOS)
848-
// XCTAssertFalse(T.isArch16Bit())
849-
// XCTAssertFalse(T.isArch32Bit())
850-
// XCTAssertTrue(T.isArch64Bit())
848+
XCTAssertFalse(T.arch?.is16Bit)
849+
XCTAssertFalse(T.arch?.is32Bit)
850+
XCTAssertTrue(T.arch?.is64Bit)
851851
V = T._macOSVersion
852852
XCTAssertEqual(V?.major, 10)
853853
XCTAssertEqual(V?.minor, 4)
@@ -860,9 +860,9 @@ final class TripleTests: XCTestCase {
860860
T = Triple("x86_64-apple-macosx10.7")
861861
XCTAssertTrue(T.os?.isMacOSX)
862862
XCTAssertFalse(T.os?.isiOS)
863-
// XCTAssertFalse(T.isArch16Bit())
864-
// XCTAssertFalse(T.isArch32Bit())
865-
// XCTAssertTrue(T.isArch64Bit())
863+
XCTAssertFalse(T.arch?.is16Bit)
864+
XCTAssertFalse(T.arch?.is32Bit)
865+
XCTAssertTrue(T.arch?.is64Bit)
866866
V = T._macOSVersion
867867
XCTAssertEqual(V?.major, 10)
868868
XCTAssertEqual(V?.minor, 7)
@@ -970,8 +970,8 @@ final class TripleTests: XCTestCase {
970970
// let GNUWindowsNormalized = Triple("i686-pc-windows-gnu-elf", normalizing: true)
971971
// XCTAssertEqual(.elf, GNUWindowsNormalized.objectFormat)
972972

973-
// let CygnusNormalised = Triple("i686-pc-windows-cygnus-elf", normalizing: true)
974-
// XCTAssertEqual(.elf, CygnusNormalised.objectFormat)
973+
// let CygnusNormalized = Triple("i686-pc-windows-cygnus-elf", normalizing: true)
974+
// XCTAssertEqual(.elf, CygnusNormalized.objectFormat)
975975

976976
let CygwinNormalized = Triple("i686-pc-cygwin-elf", normalizing: true)
977977
XCTAssertEqual(.elf, CygwinNormalized.objectFormat)

0 commit comments

Comments
 (0)