18
18
SPEC = re .compile (
19
19
r'^(?:(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
20
20
r'(?P<width>\d+)(:?/(?P<llvm_width>\d+))?)'
21
- r'|(?P<reference>\d+)(?P<modifiers>[vShdnwus]*)(?P<force_width>x\d+)?)$'
21
+ r'|(?P<reference>\d+)(?P<modifiers>[vShdnwusDMC]*)(?P<force_width>x\d+)?)'
22
+ r'(?:(?P<pointer>Pm|Pc)(?P<llvm_pointer>/.*)?)?$'
22
23
)
23
24
24
25
class PlatformInfo (object ):
@@ -80,6 +81,11 @@ def vectorize(self, length, width_info):
80
81
props .update (width_info )
81
82
return PlatformTypeInfo ('v{}{}' .format (length , self .llvm_name ), props )
82
83
84
+ def pointer (self ):
85
+ return PlatformTypeInfo ('p0{}' .format (self .llvm_name ), self .properties )
86
+
87
+ BITWIDTH_POINTER = '<pointer>'
88
+
83
89
class Type (object ):
84
90
def __init__ (self , bitwidth ):
85
91
self ._bitwidth = bitwidth
@@ -193,6 +199,39 @@ def type_info(self, platform_info):
193
199
return elem_info .vectorize (self ._length ,
194
200
platform_info .width_info (self .bitwidth ()))
195
201
202
+ class Pointer (Type ):
203
+ def __init__ (self , elem , llvm_elem , const ):
204
+ self ._elem = elem ;
205
+ self ._llvm_elem = llvm_elem
206
+ self ._const = const
207
+ Type .__init__ (self , BITWIDTH_POINTER )
208
+
209
+ def modify (self , spec , width ):
210
+ if spec == 'D' :
211
+ return self ._elem
212
+ elif spec == 'M' :
213
+ return Pointer (self ._elem , self ._llvm_elem , False )
214
+ elif spec == 'C' :
215
+ return Pointer (self ._elem , self ._llvm_elem , True )
216
+ else :
217
+ return Pointer (self ._elem .modify (spec , width ), self ._llvm_elem , self ._const )
218
+
219
+ def compiler_ctor (self ):
220
+ if self ._llvm_elem is None :
221
+ llvm_elem = 'None'
222
+ else :
223
+ llvm_elem = 'Some({})' .format (self ._llvm_elem .compiler_ctor ())
224
+ return 'p({}, {}, {})' .format ('true' if self ._const else 'false' ,
225
+ self ._elem .compiler_ctor (),
226
+ llvm_elem )
227
+
228
+ def rust_name (self ):
229
+ return '*{} {}' .format ('const' if self ._const else 'mut' ,
230
+ self ._elem .rust_name ())
231
+
232
+ def type_info (self , platform_info ):
233
+ return self ._elem .type_info (platform_info ).pointer ()
234
+
196
235
class Aggregate (Type ):
197
236
def __init__ (self , flatten , elems ):
198
237
self ._flatten = flatten
@@ -219,6 +258,22 @@ def type_info(self, platform_info):
219
258
'u' : [Unsigned ],
220
259
'f' : [Float ]}
221
260
261
+ def ptrify (match , elem , width ):
262
+ ptr = match .group ('pointer' )
263
+ if ptr is None :
264
+ return elem
265
+ else :
266
+ llvm_ptr = match .group ('llvm_pointer' )
267
+ if llvm_ptr is None :
268
+ llvm_elem = None
269
+ else :
270
+ assert llvm_ptr .startswith ('/' )
271
+ options = list (TypeSpec (llvm_ptr [1 :]).enumerate (width ))
272
+ assert len (options ) == 1
273
+ llvm_elem = options [0 ]
274
+ assert ptr in ('Pc' , 'Pm' )
275
+ return Pointer (elem , llvm_elem , ptr == 'Pc' )
276
+
222
277
class TypeSpec (object ):
223
278
def __init__ (self , spec ):
224
279
if not isinstance (spec , list ):
@@ -229,8 +284,10 @@ def __init__(self, spec):
229
284
def enumerate (self , width ):
230
285
for spec in self .spec :
231
286
match = SPEC .match (spec )
232
- if match :
287
+ assert match is not None
288
+ if True :
233
289
id = match .group ('id' )
290
+ assert id is not None
234
291
is_vector = id .islower ()
235
292
type_ctors = TYPE_ID_LOOKUP [id .lower ()]
236
293
@@ -256,19 +313,21 @@ def enumerate(self, width):
256
313
scalar = ctor (bitwidth )
257
314
258
315
if is_vector :
259
- yield Vector (scalar , width // bitwidth )
316
+ elem = Vector (scalar , width // bitwidth )
260
317
else :
261
- yield scalar
318
+ elem = scalar
319
+ yield ptrify (match , elem , width )
262
320
bitwidth *= 2
263
321
else :
264
- print ('Failed to parse: `{}`' .format (spec ), file = sys .stderr )
322
+ pass
323
+ #print('Failed to parse: `{}`'.format(spec), file=sys.stderr)
265
324
266
325
def resolve (self , width , zero ):
267
326
assert len (self .spec ) == 1
268
327
spec = self .spec [0 ]
269
328
match = SPEC .match (spec )
270
329
if match :
271
- id = match .group ('id' )
330
+ id = match .group ('id' )
272
331
if id is not None :
273
332
options = list (self .enumerate (width ))
274
333
assert len (options ) == 1
@@ -282,7 +341,7 @@ def resolve(self, width, zero):
282
341
force = match .group ('force_width' )
283
342
if force is not None :
284
343
ret = ret .modify (force , width )
285
- return ret
344
+ return ptrify ( match , ret , width )
286
345
elif spec .startswith ('(' ):
287
346
if spec .endswith (')' ):
288
347
raise NotImplementedError ()
@@ -291,6 +350,8 @@ def resolve(self, width, zero):
291
350
flatten = True
292
351
elems = [TypeSpec (subspec ).resolve (width , zero ) for subspec in true_spec .split (',' )]
293
352
return Aggregate (flatten , elems )
353
+ else :
354
+ assert False , 'Failed to resolve: {}' .format (spec )
294
355
295
356
class GenericIntrinsic (object ):
296
357
def __init__ (self , platform , intrinsic , widths , llvm_name , ret , args ):
@@ -369,7 +430,10 @@ def parse_args():
369
430
## Type specifier grammar
370
431
371
432
```
372
- type := vector | scalar | aggregate | reference
433
+ type := ( vector | scalar | aggregate | reference ) pointer?
434
+
435
+ pointer := 'Pm' llvm_pointer? | 'Pc' llvm_pointer?
436
+ llvm_pointer := '/' type
373
437
374
438
vector := vector_elem width |
375
439
vector_elem := 'i' | 'u' | 's' | 'f'
@@ -390,6 +454,18 @@ def parse_args():
390
454
number = [0-9]+
391
455
```
392
456
457
+ ## Pointers
458
+
459
+ Pointers can be created to any type. The `m` vs. `c` chooses
460
+ mut vs. const. e.g. `S32Pm` corresponds to `*mut i32`, and
461
+ `i32Pc` corresponds (with width 128) to `*const i8x16`,
462
+ `*const u32x4`, etc.
463
+
464
+ The type after the `/` (optional) represents the type used
465
+ internally to LLVM, e.g. `S32pm/S8` is exposed as `*mut i32`
466
+ in Rust, but is `i8*` in LLVM. (This defaults to the main
467
+ type).
468
+
393
469
## Vectors
394
470
395
471
The vector grammar is a pattern describing many possibilities
@@ -454,6 +530,9 @@ def parse_args():
454
530
- 'u': force an integer (vector or scalar) to be unsigned (i32x4 -> u32x4)
455
531
- 's': force an integer (vector or scalar) to be signed (u32x4 -> i32x4)
456
532
- 'x' number: force the type to be a vector of bitwidth `number`.
533
+ - 'D': dereference a pointer (*mut u32 -> u32)
534
+ - 'C': make a pointer const (*mut u32 -> *const u32)
535
+ - 'M': make a pointer mut (*const u32 -> *mut u32)
457
536
''' ))
458
537
parser .add_argument ('--format' , choices = FORMATS , required = True ,
459
538
help = 'Output format.' )
@@ -502,7 +581,7 @@ def open(self, platform):
502
581
503
582
#![allow(unused_imports)]
504
583
505
- use {{Intrinsic, i, i_, u, u_, f, v, agg}};
584
+ use {{Intrinsic, i, i_, u, u_, f, v, agg, p }};
506
585
use IntrinsicDef::Named;
507
586
use rustc::middle::ty;
508
587
0 commit comments