Skip to content

Commit bb8564d

Browse files
committed
Add ARMProfile, cannonicalARMArchName, Triple.SubArch cases. Resolve FIXME about parsing thumb architectures.
1 parent 9b4d197 commit bb8564d

File tree

2 files changed

+325
-22
lines changed

2 files changed

+325
-22
lines changed

Sources/SwiftDriver/Utilities/Triple.swift

Lines changed: 283 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -603,13 +603,41 @@ extension Triple {
603603
}
604604
}
605605

606+
enum ARMProfile {
607+
case a, r, m
608+
609+
init?<S: StringProtocol>(_ archName: S) {
610+
switch Triple.SubArch.parse(Substring(Triple.Arch.cannonicalARMArchName(from: archName))) {
611+
case .armSubArch_v6m, .armSubArch_v7m, .armSubArch_v7em,
612+
.armSubArch_v8m_mainline, .armSubArch_v8m_baseline,
613+
.armSubArch_v8_1m_mainline:
614+
self = .m
615+
case .armSubArch_v7r, .armSubArch_v8r:
616+
self = .r
617+
case .armSubArch_v7, .armSubArch_v7ve, .armSubArch_v7k,
618+
.armSubArch_v8, .armSubArch_v8_1a, .armSubArch_v8_2a,
619+
.armSubArch_v8_3a, .armSubArch_v8_4a, .armSubArch_v8_5a:
620+
self = .a
621+
case .armSubArch_v2, .armSubArch_v2a, .armSubArch_v3, .armSubArch_v3m,
622+
.armSubArch_v4, .armSubArch_v4t, .armSubArch_v5, .armSubArch_v5e,
623+
.armSubArch_v6, .armSubArch_v6k, .armSubArch_v6kz, .armSubArch_v6t2,
624+
.armSubArch_v7s,
625+
.kalimbaSubArch_v3, .kalimbaSubArch_v4, .kalimbaSubArch_v5,
626+
.mipsSubArch_r6,
627+
nil:
628+
return nil
629+
}
630+
}
631+
}
632+
606633
// Parse ARM architectures not handled by `parse`. On its own, this is not
607634
// enough to correctly parse an ARM architecture.
608635
private static func parseARMArch<S: StringProtocol>(_ archName: S) -> Triple.Arch? {
636+
609637
let ISA = ARMISA(archName: archName)
610638
let endianness = Endianness(armArchName: archName)
611639

612-
var arch: Triple.Arch? = nil
640+
let arch: Triple.Arch?
613641
switch (endianness, ISA) {
614642
case (.little, .arm):
615643
arch = .arm
@@ -623,15 +651,98 @@ extension Triple {
623651
arch = .thumbeb
624652
case (.big, .aarch64):
625653
arch = .aarch64_be
626-
default:
627-
break
654+
case (nil, _), (_, nil):
655+
arch = nil
628656
}
629657

630-
// FIXME: thumb architectures require additional validation. See LLVM's [parseARMArch](https://llvm.org/doxygen/Triple_8cpp.html#a721eb5bffb57cea96d7a9b45cbe302cf)
658+
let cannonicalArchName = cannonicalARMArchName(from: archName)
659+
660+
if cannonicalArchName.isEmpty {
661+
return nil
662+
}
663+
664+
// Thumb only exists in v4+
665+
if ISA == .thumb && (cannonicalArchName.hasPrefix("v2") || cannonicalArchName.hasPrefix("v3")) {
666+
return nil
667+
}
668+
669+
let subArch = Triple.SubArch.parse(archName)
670+
let profile = subArch?.armProfile
671+
let version = subArch?.armVersion
672+
673+
// Thumb only for v6m
674+
if profile == .m && version == 6 {
675+
if endianness == .big {
676+
return .thumbeb
677+
} else {
678+
return .thumb
679+
}
680+
}
631681

632682
return arch
633683
}
634684

685+
// Based on LLVM's ARM::getCanonicalArchName
686+
//
687+
// MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
688+
// (iwmmxt|xscale)(eb)? is also permitted. If the former, return
689+
// "v.+", if the latter, return unmodified string, minus 'eb'.
690+
// If invalid, return empty string.
691+
fileprivate static func cannonicalARMArchName<S: StringProtocol>(from arch: S) -> String {
692+
var name = Substring(arch)
693+
694+
func dropPrefix(_ prefix: String) {
695+
if name.hasPrefix(prefix) {
696+
name = name.dropFirst(prefix.count)
697+
}
698+
}
699+
700+
let possiblePrefixes = ["arm64_32", "arm64", "aarch64_32", "arm", "thumb", "aarch64"]
701+
702+
if let prefix = possiblePrefixes.first(where: name.hasPrefix) {
703+
dropPrefix(prefix)
704+
705+
if prefix == "aarch64" {
706+
// AArch64 uses "_be", not "eb" suffix.
707+
if name.contains("eb") {
708+
return ""
709+
}
710+
711+
dropPrefix("_be")
712+
}
713+
}
714+
715+
// Ex. "armebv7", move past the "eb".
716+
if name != arch {
717+
dropPrefix("eb")
718+
}
719+
// Or, if it ends with eb ("armv7eb"), chop it off.
720+
else if name.hasSuffix("eb") {
721+
name = name.dropLast(2)
722+
}
723+
724+
// Reached the end - arch is valid.
725+
if name.isEmpty {
726+
return String(arch)
727+
}
728+
729+
// Only match non-marketing names
730+
if name != arch {
731+
// Must start with 'vN'.
732+
if name.count >= 2 && (name.first != "v" || !name.dropFirst().first!.isNumber) {
733+
return ""
734+
}
735+
736+
// Can't have an extra 'eb'.
737+
if name.hasPrefix("eb") {
738+
return ""
739+
}
740+
}
741+
742+
// Arch will either be a 'v' name (v7a) or a marketing name (xscale).
743+
return String(name)
744+
}
745+
635746
private static func parseBPFArch<S: StringProtocol>(_ archName: S) -> Triple.Arch? {
636747

637748
let isLittleEndianHost = 1.littleEndian == 1
@@ -682,8 +793,174 @@ extension Triple {
682793

683794
extension Triple {
684795
public enum SubArch: Hashable {
685-
fileprivate static func parse(_ component: Substring) -> Triple.SubArch? {
686-
return nil
796+
case armSubArch_v2
797+
case armSubArch_v2a
798+
case armSubArch_v3
799+
case armSubArch_v3m
800+
case armSubArch_v4
801+
case armSubArch_v4t
802+
case armSubArch_v5
803+
case armSubArch_v5e
804+
case armSubArch_v6
805+
case armSubArch_v6k
806+
case armSubArch_v6kz
807+
case armSubArch_v6m
808+
case armSubArch_v6t2
809+
case armSubArch_v7
810+
case armSubArch_v7em
811+
case armSubArch_v7k
812+
case armSubArch_v7m
813+
case armSubArch_v7r
814+
case armSubArch_v7s
815+
case armSubArch_v7ve
816+
case armSubArch_v8
817+
case armSubArch_v8_1a
818+
case armSubArch_v8_1m_mainline
819+
case armSubArch_v8_2a
820+
case armSubArch_v8_3a
821+
case armSubArch_v8_4a
822+
case armSubArch_v8_5a
823+
case armSubArch_v8m_baseline
824+
case armSubArch_v8m_mainline
825+
case armSubArch_v8r
826+
827+
case kalimbaSubArch_v3
828+
case kalimbaSubArch_v4
829+
case kalimbaSubArch_v5
830+
831+
case mipsSubArch_r6
832+
833+
fileprivate static func parse<S: StringProtocol>(_ component: S) -> Triple.SubArch? {
834+
835+
if component.hasPrefix("mips") && (component.hasSuffix("r6el") || component.hasSuffix("r6")) {
836+
return .mipsSubArch_r6
837+
}
838+
839+
let armSubArch = Triple.Arch.cannonicalARMArchName(from: component)
840+
841+
if armSubArch.isEmpty {
842+
switch component {
843+
case _ where component.hasSuffix("kalimba3"):
844+
return .kalimbaSubArch_v3
845+
case _ where component.hasSuffix("kalimba4"):
846+
return .kalimbaSubArch_v4
847+
case _ where component.hasSuffix("kalimba5"):
848+
return .kalimbaSubArch_v5
849+
default:
850+
return nil
851+
}
852+
}
853+
854+
switch armSubArch {
855+
case "v2":
856+
return .armSubArch_v2
857+
case "v2a":
858+
return .armSubArch_v2a
859+
case "v3":
860+
return .armSubArch_v3
861+
case "v3m":
862+
return .armSubArch_v3m
863+
case "v4":
864+
return .armSubArch_v4
865+
case "v4t":
866+
return .armSubArch_v4t
867+
case "v5t":
868+
return .armSubArch_v5
869+
case "v5te", "v5tej", "xscale":
870+
return .armSubArch_v5e
871+
case "v6":
872+
return .armSubArch_v6
873+
case "v6k":
874+
return .armSubArch_v6k
875+
case "v6kz":
876+
return .armSubArch_v6kz
877+
case "v6-m":
878+
return .armSubArch_v6m
879+
case "v6t2":
880+
return .armSubArch_v6t2
881+
case "v7-a":
882+
return .armSubArch_v7
883+
case "v7k":
884+
return .armSubArch_v7k
885+
case "v7-m":
886+
return .armSubArch_v7m
887+
case "v7e-m":
888+
return .armSubArch_v7em
889+
case "v7-r":
890+
return .armSubArch_v7r
891+
case "v7s":
892+
return .armSubArch_v7s
893+
case "v7ve":
894+
return .armSubArch_v7ve
895+
case "v8-a":
896+
return .armSubArch_v8
897+
case "v8-m.main":
898+
return .armSubArch_v8m_mainline
899+
case "v8-m.base":
900+
return .armSubArch_v8m_baseline
901+
case "v8-r":
902+
return .armSubArch_v8r
903+
case "v8.1-m.main":
904+
return .armSubArch_v8_1m_mainline
905+
case "v8.1-a":
906+
return .armSubArch_v8_1a
907+
case "v8.2-a":
908+
return .armSubArch_v8_2a
909+
case "v8.3-a":
910+
return .armSubArch_v8_3a
911+
case "v8.4-a":
912+
return .armSubArch_v8_4a
913+
case "v8.5-a":
914+
return .armSubArch_v8_5a
915+
default:
916+
return nil
917+
}
918+
}
919+
920+
var armProfile: Triple.Arch.ARMProfile? {
921+
switch self {
922+
case .armSubArch_v6m, .armSubArch_v7m, .armSubArch_v7em,
923+
.armSubArch_v8m_mainline, .armSubArch_v8m_baseline,
924+
.armSubArch_v8_1m_mainline:
925+
return .m
926+
case .armSubArch_v7r, .armSubArch_v8r:
927+
return .r
928+
case .armSubArch_v7, .armSubArch_v7ve, .armSubArch_v7k,
929+
.armSubArch_v8, .armSubArch_v8_1a, .armSubArch_v8_2a,
930+
.armSubArch_v8_3a, .armSubArch_v8_4a, .armSubArch_v8_5a:
931+
return .a
932+
case .armSubArch_v2, .armSubArch_v2a, .armSubArch_v3, .armSubArch_v3m,
933+
.armSubArch_v4, .armSubArch_v4t, .armSubArch_v5, .armSubArch_v5e,
934+
.armSubArch_v6, .armSubArch_v6k, .armSubArch_v6kz, .armSubArch_v6t2,
935+
.armSubArch_v7s,
936+
.kalimbaSubArch_v3, .kalimbaSubArch_v4, .kalimbaSubArch_v5,
937+
.mipsSubArch_r6:
938+
return nil
939+
}
940+
}
941+
942+
var armVersion: Int? {
943+
switch self {
944+
case .armSubArch_v2, .armSubArch_v2a:
945+
return 2
946+
case .armSubArch_v3, .armSubArch_v3m:
947+
return 3
948+
case .armSubArch_v4, .armSubArch_v4t:
949+
return 4
950+
case .armSubArch_v5, .armSubArch_v5e:
951+
return 5
952+
case .armSubArch_v6, .armSubArch_v6k, .armSubArch_v6kz, .armSubArch_v6m, .armSubArch_v6t2:
953+
return 6
954+
case .armSubArch_v7, .armSubArch_v7em, .armSubArch_v7k, .armSubArch_v7m, .armSubArch_v7r,
955+
.armSubArch_v7s, .armSubArch_v7ve:
956+
return 7
957+
case .armSubArch_v8, .armSubArch_v8_1a, .armSubArch_v8_1m_mainline, .armSubArch_v8_2a,
958+
.armSubArch_v8_3a, .armSubArch_v8_4a, .armSubArch_v8_5a, .armSubArch_v8m_baseline,
959+
.armSubArch_v8m_mainline, .armSubArch_v8r:
960+
return 8
961+
case .kalimbaSubArch_v3, .kalimbaSubArch_v4, .kalimbaSubArch_v5, .mipsSubArch_r6:
962+
return nil
963+
}
687964
}
688965
}
689966
}

0 commit comments

Comments
 (0)