@@ -606,10 +606,11 @@ extension Triple {
606
606
// Parse ARM architectures not handled by `parse`. On its own, this is not
607
607
// enough to correctly parse an ARM architecture.
608
608
private static func parseARMArch< S: StringProtocol > ( _ archName: S ) -> Triple . Arch ? {
609
+
609
610
let ISA = ARMISA ( archName: archName)
610
611
let endianness = Endianness ( armArchName: archName)
611
612
612
- var arch : Triple . Arch ? = nil
613
+ let arch : Triple . Arch ?
613
614
switch ( endianness, ISA) {
614
615
case ( . little, . arm) :
615
616
arch = . arm
@@ -623,15 +624,94 @@ extension Triple {
623
624
arch = . thumbeb
624
625
case ( . big, . aarch64) :
625
626
arch = . aarch64_be
626
- default :
627
- break
627
+ case ( nil , _) , ( _, nil ) :
628
+ arch = nil
629
+ }
630
+
631
+ let cannonicalArchName = cannonicalARMArchName ( from: archName)
632
+
633
+ if cannonicalArchName. isEmpty {
634
+ return nil
635
+ }
636
+
637
+ // Thumb only exists in v4+
638
+ if ISA == . thumb && ( cannonicalArchName. hasPrefix ( " v2 " ) || cannonicalArchName. hasPrefix ( " v3 " ) ) {
639
+ return nil
628
640
}
629
641
630
- // FIXME: thumb architectures require additional validation. See LLVM's [parseARMArch](https://llvm.org/doxygen/Triple_8cpp.html#a721eb5bffb57cea96d7a9b45cbe302cf)
642
+ // Thumb only for v6m
643
+ if case . arm( let subArch) = Triple . SubArch. parse ( archName) , subArch. profile == . m && subArch. version == 6 {
644
+ if endianness == . big {
645
+ return . thumbeb
646
+ } else {
647
+ return . thumb
648
+ }
649
+ }
631
650
632
651
return arch
633
652
}
634
653
654
+ // Based on LLVM's ARM::getCanonicalArchName
655
+ //
656
+ // MArch is expected to be of the form (arm|thumb)?(eb)?(v.+)?(eb)?, but
657
+ // (iwmmxt|xscale)(eb)? is also permitted. If the former, return
658
+ // "v.+", if the latter, return unmodified string, minus 'eb'.
659
+ // If invalid, return empty string.
660
+ fileprivate static func cannonicalARMArchName< S: StringProtocol > ( from arch: S ) -> String {
661
+ var name = Substring ( arch)
662
+
663
+ func dropPrefix( _ prefix: String ) {
664
+ if name. hasPrefix ( prefix) {
665
+ name = name. dropFirst ( prefix. count)
666
+ }
667
+ }
668
+
669
+ let possiblePrefixes = [ " arm64_32 " , " arm64 " , " aarch64_32 " , " arm " , " thumb " , " aarch64 " ]
670
+
671
+ if let prefix = possiblePrefixes. first ( where: name. hasPrefix) {
672
+ dropPrefix ( prefix)
673
+
674
+ if prefix == " aarch64 " {
675
+ // AArch64 uses "_be", not "eb" suffix.
676
+ if name. contains ( " eb " ) {
677
+ return " "
678
+ }
679
+
680
+ dropPrefix ( " _be " )
681
+ }
682
+ }
683
+
684
+ // Ex. "armebv7", move past the "eb".
685
+ if name != arch {
686
+ dropPrefix ( " eb " )
687
+ }
688
+ // Or, if it ends with eb ("armv7eb"), chop it off.
689
+ else if name. hasSuffix ( " eb " ) {
690
+ name = name. dropLast ( 2 )
691
+ }
692
+
693
+ // Reached the end - arch is valid.
694
+ if name. isEmpty {
695
+ return String ( arch)
696
+ }
697
+
698
+ // Only match non-marketing names
699
+ if name != arch {
700
+ // Must start with 'vN'.
701
+ if name. count >= 2 && ( name. first != " v " || !name. dropFirst ( ) . first!. isNumber) {
702
+ return " "
703
+ }
704
+
705
+ // Can't have an extra 'eb'.
706
+ if name. hasPrefix ( " eb " ) {
707
+ return " "
708
+ }
709
+ }
710
+
711
+ // Arch will either be a 'v' name (v7a) or a marketing name (xscale).
712
+ return String ( name)
713
+ }
714
+
635
715
private static func parseBPFArch< S: StringProtocol > ( _ archName: S ) -> Triple . Arch ? {
636
716
637
717
let isLittleEndianHost = 1 . littleEndian == 1
@@ -682,8 +762,176 @@ extension Triple {
682
762
683
763
extension Triple {
684
764
public enum SubArch : Hashable {
685
- fileprivate static func parse( _ component: Substring ) -> Triple . SubArch ? {
686
- return nil
765
+
766
+ public enum ARM {
767
+
768
+ public enum Profile {
769
+ case a, r, m
770
+ }
771
+
772
+ case v2
773
+ case v2a
774
+ case v3
775
+ case v3m
776
+ case v4
777
+ case v4t
778
+ case v5
779
+ case v5e
780
+ case v6
781
+ case v6k
782
+ case v6kz
783
+ case v6m
784
+ case v6t2
785
+ case v7
786
+ case v7em
787
+ case v7k
788
+ case v7m
789
+ case v7r
790
+ case v7s
791
+ case v7ve
792
+ case v8
793
+ case v8_1a
794
+ case v8_1m_mainline
795
+ case v8_2a
796
+ case v8_3a
797
+ case v8_4a
798
+ case v8_5a
799
+ case v8m_baseline
800
+ case v8m_mainline
801
+ case v8r
802
+
803
+ var profile : Triple . SubArch . ARM . Profile ? {
804
+ switch self {
805
+ case . v6m, . v7m, . v7em, . v8m_mainline, . v8m_baseline, . v8_1m_mainline:
806
+ return . m
807
+ case . v7r, . v8r:
808
+ return . r
809
+ case . v7, . v7ve, . v7k, . v8, . v8_1a, . v8_2a, . v8_3a, . v8_4a, . v8_5a:
810
+ return . a
811
+ case . v2, . v2a, . v3, . v3m, . v4, . v4t, . v5, . v5e, . v6, . v6k, . v6kz, . v6t2, . v7s:
812
+ return nil
813
+ }
814
+ }
815
+
816
+ var version : Int {
817
+ switch self {
818
+ case . v2, . v2a:
819
+ return 2
820
+ case . v3, . v3m:
821
+ return 3
822
+ case . v4, . v4t:
823
+ return 4
824
+ case . v5, . v5e:
825
+ return 5
826
+ case . v6, . v6k, . v6kz, . v6m, . v6t2:
827
+ return 6
828
+ case . v7, . v7em, . v7k, . v7m, . v7r, . v7s, . v7ve:
829
+ return 7
830
+ case . v8, . v8_1a, . v8_1m_mainline, . v8_2a, . v8_3a, . v8_4a, . v8_5a, . v8m_baseline, . v8m_mainline, . v8r:
831
+ return 8
832
+ }
833
+ }
834
+ }
835
+
836
+ public enum Kalimba {
837
+ case v3
838
+ case v4
839
+ case v5
840
+ }
841
+
842
+ public enum MIPS {
843
+ case r6
844
+ }
845
+
846
+ case arm( ARM )
847
+ case kalimba( Kalimba )
848
+ case mips( MIPS )
849
+
850
+ fileprivate static func parse< S: StringProtocol > ( _ component: S ) -> Triple . SubArch ? {
851
+
852
+ if component. hasPrefix ( " mips " ) && ( component. hasSuffix ( " r6el " ) || component. hasSuffix ( " r6 " ) ) {
853
+ return . mips( . r6)
854
+ }
855
+
856
+ let armSubArch = Triple . Arch. cannonicalARMArchName ( from: component)
857
+
858
+ if armSubArch. isEmpty {
859
+ switch component {
860
+ case _ where component. hasSuffix ( " kalimba3 " ) :
861
+ return . kalimba( . v3)
862
+ case _ where component. hasSuffix ( " kalimba4 " ) :
863
+ return . kalimba( . v4)
864
+ case _ where component. hasSuffix ( " kalimba5 " ) :
865
+ return . kalimba( . v5)
866
+ default :
867
+ return nil
868
+ }
869
+ }
870
+
871
+ switch armSubArch {
872
+ case " v2 " :
873
+ return . arm( . v2)
874
+ case " v2a " :
875
+ return . arm( . v2a)
876
+ case " v3 " :
877
+ return . arm( . v3)
878
+ case " v3m " :
879
+ return . arm( . v3m)
880
+ case " v4 " :
881
+ return . arm( . v4)
882
+ case " v4t " :
883
+ return . arm( . v4t)
884
+ case " v5t " :
885
+ return . arm( . v5)
886
+ case " v5te " , " v5tej " , " xscale " :
887
+ return . arm( . v5e)
888
+ case " v6 " :
889
+ return . arm( . v6)
890
+ case " v6k " :
891
+ return . arm( . v6k)
892
+ case " v6kz " :
893
+ return . arm( . v6kz)
894
+ case " v6-m " :
895
+ return . arm( . v6m)
896
+ case " v6t2 " :
897
+ return . arm( . v6t2)
898
+ case " v7-a " :
899
+ return . arm( . v7)
900
+ case " v7k " :
901
+ return . arm( . v7k)
902
+ case " v7-m " :
903
+ return . arm( . v7m)
904
+ case " v7e-m " :
905
+ return . arm( . v7em)
906
+ case " v7-r " :
907
+ return . arm( . v7r)
908
+ case " v7s " :
909
+ return . arm( . v7s)
910
+ case " v7ve " :
911
+ return . arm( . v7ve)
912
+ case " v8-a " :
913
+ return . arm( . v8)
914
+ case " v8-m.main " :
915
+ return . arm( . v8m_mainline)
916
+ case " v8-m.base " :
917
+ return . arm( . v8m_baseline)
918
+ case " v8-r " :
919
+ return . arm( . v8r)
920
+ case " v8.1-m.main " :
921
+ return . arm( . v8_1m_mainline)
922
+ case " v8.1-a " :
923
+ return . arm( . v8_1a)
924
+ case " v8.2-a " :
925
+ return . arm( . v8_2a)
926
+ case " v8.3-a " :
927
+ return . arm( . v8_3a)
928
+ case " v8.4-a " :
929
+ return . arm( . v8_4a)
930
+ case " v8.5-a " :
931
+ return . arm( . v8_5a)
932
+ default :
933
+ return nil
934
+ }
687
935
}
688
936
}
689
937
}
0 commit comments