@@ -23,13 +23,73 @@ impl IntrinsicTypeDefinition for X86IntrinsicType {
23
23
// matches __m128, __m256 and similar types
24
24
let re = Regex :: new ( r"\__m\d+\" ) . unwrap ( ) ;
25
25
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 ( ) ,
27
27
_ => unreachable ! ( "Shouldn't be called on this type" ) ,
28
28
}
29
29
}
30
30
31
31
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 ( ) ;
33
93
}
34
94
35
95
/// Determines the load function for this type.
@@ -124,6 +184,7 @@ impl X86IntrinsicType {
124
184
// The assumption is that the parameter of type void may have param.type
125
185
// as "__m128i", "__mmask8" and the like.
126
186
ret. set_metadata ( "etype" . to_string ( ) , param. etype . clone ( ) ) ;
187
+ ret. set_metadata ( "memwidth" . to_string ( ) , param. memwidth . to_string ( ) ) ;
127
188
if !param. etype . is_empty ( ) {
128
189
match TypeKind :: from_str ( param. etype . as_str ( ) ) {
129
190
Ok ( value) => {
@@ -155,16 +216,26 @@ impl X86IntrinsicType {
155
216
156
217
// then check the param.type and extract numeric part if there are double
157
218
// 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
+ }
158
232
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
+ }
168
239
169
240
// if param.etype == IMM, then it is a constant.
170
241
// else it stays unchanged.
0 commit comments