@@ -5,7 +5,7 @@ use std::marker::PhantomData;
5
5
use std:: ops:: Deref ;
6
6
use std:: str;
7
7
8
- use rustc_abi:: { HasDataLayout , Size , TargetDataLayout , VariantIdx } ;
8
+ use rustc_abi:: { AddressSpace , HasDataLayout , Size , TargetDataLayout , VariantIdx } ;
9
9
use rustc_codegen_ssa:: back:: versioned_llvm_target;
10
10
use rustc_codegen_ssa:: base:: { wants_msvc_seh, wants_wasm_eh} ;
11
11
use rustc_codegen_ssa:: common:: TypeKind ;
@@ -858,6 +858,179 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
858
858
)
859
859
}
860
860
}
861
+
862
+ /// Returns the llvm intrinsic ID and type parameters for an llvm intrinsic
863
+ /// `full_name` must start with `b"llvm."`
864
+ ///
865
+ /// Returns `None` if this is not a valid intrinsic name
866
+ fn parse_intrinsic_name ( & self , full_name : & [ u8 ] ) -> Option < ( llvm:: Intrinsic , Vec < & ' ll Type > ) > {
867
+ let intrinsic = llvm:: Intrinsic :: lookup ( full_name) ?;
868
+ let mut type_params = Vec :: new ( ) ;
869
+
870
+ let base_name = intrinsic. base_name ( ) ;
871
+ assert ! ( full_name. starts_with( base_name) ) ;
872
+
873
+ if intrinsic. is_overloaded ( ) {
874
+ let mut remainder = & full_name[ base_name. len ( ) ..] ;
875
+ while !remainder. is_empty ( ) {
876
+ if remainder[ 0 ] != b'.' {
877
+ let & last_ty = type_params. last ( ) ?;
878
+ let last_ty_was_ptr = match self . type_kind ( last_ty) {
879
+ TypeKind :: Pointer => true ,
880
+ TypeKind :: Array | TypeKind :: Vector | TypeKind :: ScalableVector => {
881
+ self . type_kind ( self . element_type ( last_ty) ) == TypeKind :: Pointer
882
+ }
883
+ _ => false ,
884
+ } ;
885
+
886
+ if last_ty_was_ptr {
887
+ // little support for deprecated type-specific pointers, we can disambiguate them only in these cases
888
+ let ( _element_type, new_remainder) = self . demangle_type_str ( remainder) ?;
889
+ remainder = new_remainder;
890
+
891
+ if remainder. is_empty ( ) {
892
+ break ;
893
+ }
894
+ if remainder[ 0 ] != b'.' {
895
+ return None ;
896
+ }
897
+ }
898
+ }
899
+ let ( type_param, new_remainder) = self . demangle_type_str ( & remainder[ 1 ..] ) ?;
900
+ type_params. push ( type_param) ;
901
+ remainder = new_remainder;
902
+ }
903
+
904
+ if type_params. is_empty ( ) {
905
+ // overloaded intrinsic must have at least 1 type parameter
906
+ return None ;
907
+ }
908
+ } else {
909
+ if full_name != base_name {
910
+ // for non-overloaded intrinsic, the base name is the whole name
911
+ return None ;
912
+ }
913
+ }
914
+
915
+ Some ( ( intrinsic, type_params) )
916
+ }
917
+
918
+ /// Inverse of the llvm function `getMangledTypeStr` (well, not perfect, because the
919
+ /// mangling is not fully reversible, but this is the best solution we currently have)
920
+ ///
921
+ /// FIXME(future): find out a better way to do this
922
+ fn demangle_type_str < ' a > ( & self , mangled : & ' a [ u8 ] ) -> Option < ( & ' ll Type , & ' a [ u8 ] ) > {
923
+ fn parse_int ( string : & [ u8 ] ) -> Option < ( u64 , & [ u8 ] ) > {
924
+ let mut position = 0 ;
925
+ let mut number = 0 ;
926
+
927
+ while let Some ( & digit @ b'0' ..=b'9' ) = string. get ( position) {
928
+ number = 10 * number + ( digit - b'0' ) as u64 ;
929
+ position += 1 ;
930
+ }
931
+
932
+ if position != 0 { Some ( ( number, & string[ position..] ) ) } else { None }
933
+ }
934
+
935
+ Some ( if mangled. starts_with ( b"isVoid" ) {
936
+ ( self . type_void ( ) , & mangled[ 6 ..] )
937
+ } else if mangled. starts_with ( b"Metadata" ) {
938
+ ( self . type_metadata ( ) , & mangled[ 8 ..] )
939
+ } else if mangled. starts_with ( b"f16" ) {
940
+ ( self . type_f16 ( ) , & mangled[ 3 ..] )
941
+ } else if mangled. starts_with ( b"bf16" ) {
942
+ ( self . type_bf16 ( ) , & mangled[ 4 ..] )
943
+ } else if mangled. starts_with ( b"f32" ) {
944
+ ( self . type_f32 ( ) , & mangled[ 3 ..] )
945
+ } else if mangled. starts_with ( b"f64" ) {
946
+ ( self . type_f64 ( ) , & mangled[ 3 ..] )
947
+ } else if mangled. starts_with ( b"f80" ) {
948
+ ( self . type_x86f80 ( ) , & mangled[ 3 ..] )
949
+ } else if mangled. starts_with ( b"f128" ) {
950
+ ( self . type_f128 ( ) , & mangled[ 4 ..] )
951
+ } else if mangled. starts_with ( b"ppcf128" ) {
952
+ ( self . type_ppcf128 ( ) , & mangled[ 7 ..] )
953
+ } else if mangled. starts_with ( b"x86amx" ) {
954
+ ( self . type_x86amx ( ) , & mangled[ 6 ..] )
955
+ } else if mangled. starts_with ( b"i" ) {
956
+ // integer type
957
+ let ( int_width, remainder) = parse_int ( & mangled[ 1 ..] ) ?;
958
+ ( self . type_ix ( int_width) , remainder)
959
+ } else if mangled. starts_with ( b"p" ) {
960
+ // pointer type
961
+ let ( address_space, remainder) = parse_int ( & mangled[ 1 ..] ) ?;
962
+ let address_space = AddressSpace ( address_space. try_into ( ) . unwrap ( ) ) ;
963
+ ( self . type_ptr_ext ( address_space) , remainder)
964
+ } else if mangled. starts_with ( b"v" ) {
965
+ // vector type
966
+ let ( element_count, remainder) = parse_int ( & mangled[ 1 ..] ) ?;
967
+ let ( element_type, remainder) = self . demangle_type_str ( remainder) ?;
968
+ ( self . type_vector ( element_type, element_count) , remainder)
969
+ } else if mangled. starts_with ( b"nxv" ) {
970
+ // scalable vector
971
+ let ( element_count, remainder) = parse_int ( & mangled[ 3 ..] ) ?;
972
+ let ( element_type, remainder) = self . demangle_type_str ( remainder) ?;
973
+ ( self . type_scalable_vector ( element_type, element_count) , remainder)
974
+ } else if mangled. starts_with ( b"a" ) {
975
+ // array type
976
+ let ( element_count, remainder) = parse_int ( & mangled[ 1 ..] ) ?;
977
+ let ( element_type, remainder) = self . demangle_type_str ( remainder) ?;
978
+ ( self . type_array ( element_type, element_count) , remainder)
979
+ } else if mangled. starts_with ( b"sl_" ) {
980
+ // literal struct
981
+ let mut remainder = & mangled[ 3 ..] ;
982
+ let mut fields = Vec :: new ( ) ;
983
+ loop {
984
+ if remainder. is_empty ( ) {
985
+ // struct types should end with an `s`
986
+ return None ;
987
+ }
988
+ if remainder[ 0 ] == b's'
989
+ && !remainder. starts_with ( b"s_" )
990
+ && !remainder. starts_with ( b"sl_" )
991
+ {
992
+ break ( self . type_struct ( & fields, true ) , & remainder[ 1 ..] ) ;
993
+ }
994
+ let ( field, new_remainder) = self . demangle_type_str ( remainder) ?;
995
+ fields. push ( field) ;
996
+ remainder = new_remainder;
997
+ }
998
+ } else if mangled. starts_with ( b"f_" ) {
999
+ // function type
1000
+ let ( return_type, mut remainder) = self . demangle_type_str ( & mangled[ 2 ..] ) ?;
1001
+ let mut parameters = Vec :: new ( ) ;
1002
+ loop {
1003
+ if remainder. is_empty ( ) {
1004
+ // function types should end with an `f`
1005
+ return None ;
1006
+ }
1007
+ if remainder. starts_with ( b"varargf" ) {
1008
+ break ( self . type_variadic_func ( & parameters, return_type) , & remainder[ 7 ..] ) ;
1009
+ }
1010
+ if remainder[ 0 ] == b'f' && !remainder. starts_with ( b"f_" ) {
1011
+ break ( self . type_func ( & parameters, return_type) , & remainder[ 1 ..] ) ;
1012
+ }
1013
+ let ( parameter, new_remainder) = self . demangle_type_str ( remainder) ?;
1014
+ parameters. push ( parameter) ;
1015
+ remainder = new_remainder;
1016
+ }
1017
+ } else if mangled. starts_with ( b"s_" ) || mangled. starts_with ( b"t" ) {
1018
+ // non-literal structs and target types
1019
+ // these types can't be parsed unambiguously, because they have their name in the mangling
1020
+ unimplemented ! ( "non-literal structs and TargetExt types are not supported yet" )
1021
+ } else {
1022
+ // invalid type
1023
+ return None ;
1024
+ } )
1025
+ }
1026
+
1027
+ pub ( crate ) fn get_intrinsic_from_name (
1028
+ & self ,
1029
+ full_name : & [ u8 ] ,
1030
+ ) -> Option < ( & ' ll Type , & ' ll Value ) > {
1031
+ let ( intrinsic, type_params) = self . parse_intrinsic_name ( full_name) ?;
1032
+ Some ( self . get_intrinsic ( intrinsic, & type_params) )
1033
+ }
861
1034
}
862
1035
863
1036
impl < ' ll > CodegenCx < ' ll , ' _ > {
0 commit comments