19
19
SPEC = re .compile (
20
20
r'^(?:(?P<void>V)|(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
21
21
r'(?P<width>\d+)(:?/(?P<llvm_width>\d+))?)'
22
- r'|(?P<reference>\d+)(?P<modifiers>[vShdnwusDMC]*)(?P<force_width>x\d+)?) '
23
- r'(?:(?P<pointer>Pm|Pc)(?P<llvm_pointer>/.*)?)?$'
22
+ r'|(?P<reference>\d+)) (?P<modifiers>[vShdnwusDMC]*)(?P<force_width>x\d+)?'
23
+ r'(?:(?P<pointer>Pm|Pc)(?P<llvm_pointer>/.*)?|(?P<bitcast>->.*) )?$'
24
24
)
25
25
26
26
class PlatformInfo (object ):
@@ -74,6 +74,9 @@ def __init__(self, llvm_name, properties):
74
74
self .properties = properties
75
75
self .llvm_name = llvm_name
76
76
77
+ def __repr__ (self ):
78
+ return '<PlatformTypeInfo {}, {}>' .format (self .llvm_name , self .properties )
79
+
77
80
def __getattr__ (self , name ):
78
81
return self .properties [name ]
79
82
@@ -94,9 +97,12 @@ def __init__(self, bitwidth):
94
97
def bitwidth (self ):
95
98
return self ._bitwidth
96
99
97
- def modify (self , spec , width ):
100
+ def modify (self , spec , width , previous ):
98
101
raise NotImplementedError ()
99
102
103
+ def __ne__ (self , other ):
104
+ return not (self == other )
105
+
100
106
class Void (Type ):
101
107
def __init__ (self ):
102
108
Type .__init__ (self , 0 )
@@ -110,11 +116,14 @@ def rust_name(self):
110
116
def type_info (self , platform_info ):
111
117
return None
112
118
119
+ def __eq__ (self , other ):
120
+ return isinstance (other , Void )
121
+
113
122
class Number (Type ):
114
123
def __init__ (self , bitwidth ):
115
124
Type .__init__ (self , bitwidth )
116
125
117
- def modify (self , spec , width ):
126
+ def modify (self , spec , width , previous ):
118
127
if spec == 'u' :
119
128
return Unsigned (self .bitwidth ())
120
129
elif spec == 's' :
@@ -131,11 +140,16 @@ def modify(self, spec, width):
131
140
def type_info (self , platform_info ):
132
141
return platform_info .number_type_info (self )
133
142
143
+ def __eq__ (self , other ):
144
+ # print(self, other)
145
+ return self .__class__ == other .__class__ and self .bitwidth () == other .bitwidth ()
146
+
134
147
class Signed (Number ):
135
148
def __init__ (self , bitwidth , llvm_bitwidth = None ):
136
149
Number .__init__ (self , bitwidth )
137
150
self ._llvm_bitwidth = llvm_bitwidth
138
151
152
+
139
153
def compiler_ctor (self ):
140
154
if self ._llvm_bitwidth is None :
141
155
return 'i({})' .format (self .bitwidth ())
@@ -184,26 +198,47 @@ def rust_name(self):
184
198
return 'f{}' .format (self .bitwidth ())
185
199
186
200
class Vector (Type ):
187
- def __init__ (self , elem , length ):
201
+ def __init__ (self , elem , length , bitcast = None ):
188
202
assert isinstance (elem , Type ) and not isinstance (elem , Vector )
189
203
Type .__init__ (self ,
190
204
elem .bitwidth () * length )
191
205
self ._length = length
192
206
self ._elem = elem
207
+ assert bitcast is None or (isinstance (bitcast , Vector ) and
208
+ bitcast ._bitcast is None and
209
+ bitcast ._elem .bitwidth () == elem .bitwidth ())
210
+ if bitcast is not None and bitcast ._elem != elem :
211
+ self ._bitcast = bitcast ._elem
212
+ else :
213
+ self ._bitcast = None
193
214
194
- def modify (self , spec , width ):
195
- if spec == 'h' :
215
+ def modify (self , spec , width , previous ):
216
+ if spec == 'S' :
217
+ return self ._elem
218
+ elif spec == 'h' :
196
219
return Vector (self ._elem , self ._length // 2 )
197
220
elif spec == 'd' :
198
221
return Vector (self ._elem , self ._length * 2 )
199
222
elif spec .startswith ('x' ):
200
223
new_bitwidth = int (spec [1 :])
201
224
return Vector (self ._elem , new_bitwidth // self ._elem .bitwidth ())
225
+ elif spec .startswith ('->' ):
226
+ bitcast_to = TypeSpec (spec [2 :])
227
+ choices = list (bitcast_to .enumerate (width , previous ))
228
+ assert len (choices ) == 1
229
+ bitcast_to = choices [0 ]
230
+ return Vector (self ._elem , self ._length , bitcast_to )
202
231
else :
203
- return Vector (self ._elem .modify (spec , width ), self ._length )
232
+ return Vector (self ._elem .modify (spec , width , previous ), self ._length )
204
233
205
234
def compiler_ctor (self ):
206
- return 'v({}, {})' .format (self ._elem .compiler_ctor (), self ._length )
235
+ if self ._bitcast is None :
236
+ return 'v({}, {})' .format (self ._elem .compiler_ctor (),
237
+ self ._length )
238
+ else :
239
+ return 'v_({}, {}, {})' .format (self ._elem .compiler_ctor (),
240
+ self ._bitcast .compiler_ctor (),
241
+ self ._length )
207
242
208
243
def rust_name (self ):
209
244
return '{}x{}' .format (self ._elem .rust_name (), self ._length )
@@ -213,22 +248,26 @@ def type_info(self, platform_info):
213
248
return elem_info .vectorize (self ._length ,
214
249
platform_info .width_info (self .bitwidth ()))
215
250
251
+ def __eq__ (self , other ):
252
+ return isinstance (other , Vector ) and self ._length == other ._length and \
253
+ self ._elem == other ._elem and self ._bitcast == other ._bitcast
254
+
216
255
class Pointer (Type ):
217
256
def __init__ (self , elem , llvm_elem , const ):
218
257
self ._elem = elem ;
219
258
self ._llvm_elem = llvm_elem
220
259
self ._const = const
221
260
Type .__init__ (self , BITWIDTH_POINTER )
222
261
223
- def modify (self , spec , width ):
262
+ def modify (self , spec , width , previous ):
224
263
if spec == 'D' :
225
264
return self ._elem
226
265
elif spec == 'M' :
227
266
return Pointer (self ._elem , self ._llvm_elem , False )
228
267
elif spec == 'C' :
229
268
return Pointer (self ._elem , self ._llvm_elem , True )
230
269
else :
231
- return Pointer (self ._elem .modify (spec , width ), self ._llvm_elem , self ._const )
270
+ return Pointer (self ._elem .modify (spec , width , previous ), self ._llvm_elem , self ._const )
232
271
233
272
def compiler_ctor (self ):
234
273
if self ._llvm_elem is None :
@@ -246,6 +285,10 @@ def rust_name(self):
246
285
def type_info (self , platform_info ):
247
286
return self ._elem .type_info (platform_info ).pointer ()
248
287
288
+ def __eq__ (self , other ):
289
+ return isinstance (other , Pointer ) and self ._const == other ._const \
290
+ and self ._elem == other ._elem and self ._llvm_elem == other ._llvm_elem
291
+
249
292
class Aggregate (Type ):
250
293
def __init__ (self , flatten , elems ):
251
294
self ._flatten = flatten
@@ -266,6 +309,10 @@ def type_info(self, platform_info):
266
309
#return PlatformTypeInfo(None, None, self._llvm_name)
267
310
return None
268
311
312
+ def __eq__ (self , other ):
313
+ return isinstance (other , Aggregate ) and self ._flatten == other ._flatten and \
314
+ self ._elems == other ._elems
315
+
269
316
270
317
TYPE_ID_LOOKUP = {'i' : [Signed , Unsigned ],
271
318
's' : [Signed ],
@@ -302,6 +349,14 @@ def enumerate(self, width, previous):
302
349
id = match .group ('id' )
303
350
reference = match .group ('reference' )
304
351
352
+ modifiers = list (match .group ('modifiers' ) or '' )
353
+ force = match .group ('force_width' )
354
+ if force is not None :
355
+ modifiers .append (force )
356
+ bitcast = match .group ('bitcast' )
357
+ if bitcast is not None :
358
+ modifiers .append (bitcast )
359
+
305
360
if match .group ('void' ) is not None :
306
361
assert spec == 'V'
307
362
yield Void ()
@@ -333,7 +388,11 @@ def enumerate(self, width, previous):
333
388
if is_vector :
334
389
elem = Vector (scalar , width // bitwidth )
335
390
else :
391
+ assert bitcast is None
336
392
elem = scalar
393
+
394
+ for x in modifiers :
395
+ elem = elem .modify (x , width , previous )
337
396
yield ptrify (match , elem , width , previous )
338
397
bitwidth *= 2
339
398
elif reference is not None :
@@ -342,15 +401,13 @@ def enumerate(self, width, previous):
342
401
'referring to argument {}, but only {} are known' .format (reference ,
343
402
len (previous ))
344
403
ret = previous [reference ]
345
- for x in match .group ('modifiers' ) or []:
346
- ret = ret .modify (x , width )
347
- force = match .group ('force_width' )
348
- if force is not None :
349
- ret = ret .modify (force , width )
404
+ for x in modifiers :
405
+ ret = ret .modify (x , width , previous )
350
406
yield ptrify (match , ret , width , previous )
351
407
else :
352
408
assert False , 'matched `{}`, but didn\' t understand it?' .format (spec )
353
409
elif spec .startswith ('(' ):
410
+ assert bitcast is None
354
411
if spec .endswith (')' ):
355
412
raise NotImplementedError ()
356
413
elif spec .endswith (')f' ):
@@ -452,12 +509,16 @@ def parse_args():
452
509
## Type specifier grammar
453
510
454
511
```
455
- type := core_type pointer ?
512
+ type := core_type modifier* suffix ?
456
513
457
514
core_type := void | vector | scalar | aggregate | reference
458
515
516
+ modifier := 'v' | 'h' | 'd' | 'n' | 'w' | 'u' | 's' |
517
+ 'x' number
518
+ suffix := pointer | bitcast
459
519
pointer := 'Pm' llvm_pointer? | 'Pc' llvm_pointer?
460
520
llvm_pointer := '/' type
521
+ bitcast := '->' type
461
522
462
523
void := 'V'
463
524
@@ -470,28 +531,13 @@ def parse_args():
470
531
471
532
aggregate := '(' (type),* ')' 'f'?
472
533
473
- reference := number modifiers*
474
- modifiers := 'v' | 'h' | 'd' | 'n' | 'w' | 'u' | 's' |
475
- 'x' number
476
-
534
+ reference := number
477
535
478
536
width = number | '(' number '-' number ')'
479
537
480
538
number = [0-9]+
481
539
```
482
540
483
- ## Pointers
484
-
485
- Pointers can be created to any type. The `m` vs. `c` chooses
486
- mut vs. const. e.g. `S32Pm` corresponds to `*mut i32`, and
487
- `i32Pc` corresponds (with width 128) to `*const i8x16`,
488
- `*const u32x4`, etc.
489
-
490
- The type after the `/` (optional) represents the type used
491
- internally to LLVM, e.g. `S32pm/S8` is exposed as `*mut i32`
492
- in Rust, but is `i8*` in LLVM. (This defaults to the main
493
- type).
494
-
495
541
## Void
496
542
497
543
The `V` type corresponds to `void` in LLVM (`()` in
@@ -550,6 +596,11 @@ def parse_args():
550
596
with 0 == return value, 1 == first argument, 2 == second
551
597
argument, etc.
552
598
599
+ ## Affixes
600
+
601
+ The `modifier` and `suffix` adaptors change the precise
602
+ representation.
603
+
553
604
### Modifiers
554
605
555
606
- 'v': put a scalar into a vector of the current width (u32 -> u32x4, when width == 128)
@@ -563,6 +614,26 @@ def parse_args():
563
614
- 'D': dereference a pointer (*mut u32 -> u32)
564
615
- 'C': make a pointer const (*mut u32 -> *const u32)
565
616
- 'M': make a pointer mut (*const u32 -> *mut u32)
617
+
618
+ ### Pointers
619
+
620
+ Pointers can be created of any type by appending a `P*`
621
+ suffix. The `m` vs. `c` chooses mut vs. const. e.g. `S32Pm`
622
+ corresponds to `*mut i32`, and `i32Pc` corresponds (with width
623
+ 128) to `*const i8x16`, `*const u32x4`, etc.
624
+
625
+ The type after the `/` (optional) represents the type used
626
+ internally to LLVM, e.g. `S32pm/S8` is exposed as `*mut i32`
627
+ in Rust, but is `i8*` in LLVM. (This defaults to the main
628
+ type).
629
+
630
+ ### Bitcast
631
+
632
+ The `'->' type` bitcast suffix will cause the value to be
633
+ bitcast to the right-hand type when calling the intrinsic,
634
+ e.g. `s32->f32` will expose the intrinsic as `i32x4` at the
635
+ Rust level, but will cast that vector to `f32x4` when calling
636
+ the LLVM intrinsic.
566
637
''' ))
567
638
parser .add_argument ('--format' , choices = FORMATS , required = True ,
568
639
help = 'Output format.' )
@@ -611,7 +682,7 @@ def open(self, platform):
611
682
612
683
#![allow(unused_imports)]
613
684
614
- use {{Intrinsic, i, i_, u, u_, f, v, agg, p, void}};
685
+ use {{Intrinsic, i, i_, u, u_, f, v, v_, agg, p, void}};
615
686
use IntrinsicDef::Named;
616
687
use rustc::middle::ty;
617
688
0 commit comments