@@ -23,13 +23,73 @@ impl IntrinsicTypeDefinition for X86IntrinsicType {
2323 // matches __m128, __m256 and similar types
2424 let re = Regex :: new ( r"\__m\d+\" ) . unwrap ( ) ;
2525 match self . metadata . get ( "type" ) {
26- Some ( type_data) if re. is_match ( type_data) => type_data. to_string ( ) ,
26+ Some ( type_data) if re. is_match ( type_data) => type_data. to_string ( ) ,
2727 _ => unreachable ! ( "Shouldn't be called on this type" ) ,
2828 }
2929 }
3030
3131 fn rust_type ( & self ) -> String {
32- todo ! ( "rust_type for X86IntrinsicType needs to be implemented!" ) ;
32+ // handling edge cases first
33+ // the general handling is implemented below
34+ if let Some ( val) = self . metadata . get ( "type" ) {
35+ match val. as_str ( ) {
36+ "__m128 const *" => {
37+ return "&__m128" . to_string ( ) ;
38+ }
39+ "__m128d const *" => {
40+ return "&__m128d" . to_string ( ) ;
41+ }
42+ "const void*" => {
43+ return "&__m128d" . to_string ( ) ;
44+ }
45+ _ => { }
46+ }
47+ }
48+
49+ if self . kind ( ) == TypeKind :: Void && self . ptr {
50+ // this has been handled by default settings in
51+ // the from_param function of X86IntrinsicType
52+ unreachable ! ( )
53+ }
54+
55+ // general handling cases
56+ let core_part = if self . kind ( ) == TypeKind :: Mask {
57+ // all types of __mmask<int> are handled here
58+ format ! ( "__mask{}" , self . bit_len. unwrap( ) )
59+ } else if self . simd_len . is_some ( ) {
60+ // all types of __m<int> vector types are handled here
61+ let re = Regex :: new ( r"\__m\d+[a-z]*" ) . unwrap ( ) ;
62+ let rust_type = self
63+ . metadata
64+ . get ( "type" )
65+ . map ( |val| re. find ( val) . unwrap ( ) . as_str ( ) ) ;
66+ rust_type. unwrap ( ) . to_string ( )
67+ } else {
68+ format ! (
69+ "{}{}" ,
70+ self . kind. rust_prefix( ) . to_string( ) ,
71+ self . bit_len. unwrap( )
72+ )
73+ } ;
74+
75+ // extracting "memsize" so that even vector types can be involved
76+ let memwidth = self
77+ . metadata
78+ . get ( "memwidth" )
79+ . map ( |n| str:: parse :: < u32 > ( n) . unwrap ( ) ) ;
80+ let prefix_part = if self . ptr && self . constant && self . bit_len . eq ( & memwidth) {
81+ "&"
82+ } else if self . ptr && self . bit_len . eq ( & memwidth) {
83+ "&mut "
84+ } else if self . ptr && self . constant {
85+ "*const "
86+ } else if self . ptr {
87+ "*mut "
88+ } else {
89+ ""
90+ } ;
91+
92+ return prefix_part. to_string ( ) + core_part. as_str ( ) ;
3393 }
3494
3595 /// Determines the load function for this type.
@@ -124,6 +184,7 @@ impl X86IntrinsicType {
124184 // The assumption is that the parameter of type void may have param.type
125185 // as "__m128i", "__mmask8" and the like.
126186 ret. set_metadata ( "etype" . to_string ( ) , param. etype . clone ( ) ) ;
187+ ret. set_metadata ( "memwidth" . to_string ( ) , param. memwidth . to_string ( ) ) ;
127188 if !param. etype . is_empty ( ) {
128189 match TypeKind :: from_str ( param. etype . as_str ( ) ) {
129190 Ok ( value) => {
@@ -155,16 +216,26 @@ impl X86IntrinsicType {
155216
156217 // then check the param.type and extract numeric part if there are double
157218 // underscores. divide this number with bit-len and set this as simd-len.
219+ // Only __m<int> types can have a simd-len.
220+ if param. type_data . matches ( "__m" ) . next ( ) . is_some ( )
221+ && param. type_data . matches ( "__mmask" ) . next ( ) . is_none ( )
222+ {
223+ let mut type_processed = param. type_data . clone ( ) ;
224+ type_processed. retain ( |c| c. is_numeric ( ) ) ;
225+ ret. vec_len = match str:: parse :: < u32 > ( type_processed. as_str ( ) ) {
226+ // If bit_len is None, vec_len will be None.
227+ // Else vec_len will be (num_bits / bit_len).
228+ Ok ( num_bits) => ret. bit_len . and ( Some ( num_bits / ret. bit_len . unwrap ( ) ) ) ,
229+ Err ( _) => None ,
230+ } ;
231+ }
158232
159- let mut type_processed = param. type_data . clone ( ) ;
160- type_processed. retain ( |c| c. is_numeric ( ) ) ;
161-
162- ret. vec_len = match str:: parse :: < u32 > ( type_processed. as_str ( ) ) {
163- // If bit_len is None, vec_len will be None.
164- // Else vec_len will be (num_bits / bit_len).
165- Ok ( num_bits) => ret. bit_len . and ( Some ( num_bits / ret. bit_len . unwrap ( ) ) ) ,
166- Err ( _) => None ,
167- } ;
233+ // default settings for "void *" parameters
234+ // often used by intrinsics to denote memory address or so.
235+ if ret. kind == TypeKind :: Void && ret. ptr {
236+ ret. kind = TypeKind :: Int ( Sign :: Unsigned ) ;
237+ ret. bit_len = Some ( 8 ) ;
238+ }
168239
169240 // if param.etype == IMM, then it is a constant.
170241 // else it stays unchanged.
0 commit comments