1818SPEC = re .compile (
1919 r'^(?:(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
2020 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>/.*)?)?$'
2223)
2324
2425class PlatformInfo (object ):
@@ -80,6 +81,11 @@ def vectorize(self, length, width_info):
8081 props .update (width_info )
8182 return PlatformTypeInfo ('v{}{}' .format (length , self .llvm_name ), props )
8283
84+ def pointer (self ):
85+ return PlatformTypeInfo ('p0{}' .format (self .llvm_name ), self .properties )
86+
87+ BITWIDTH_POINTER = '<pointer>'
88+
8389class Type (object ):
8490 def __init__ (self , bitwidth ):
8591 self ._bitwidth = bitwidth
@@ -193,6 +199,39 @@ def type_info(self, platform_info):
193199 return elem_info .vectorize (self ._length ,
194200 platform_info .width_info (self .bitwidth ()))
195201
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+
196235class Aggregate (Type ):
197236 def __init__ (self , flatten , elems ):
198237 self ._flatten = flatten
@@ -219,6 +258,22 @@ def type_info(self, platform_info):
219258 'u' : [Unsigned ],
220259 'f' : [Float ]}
221260
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+
222277class TypeSpec (object ):
223278 def __init__ (self , spec ):
224279 if not isinstance (spec , list ):
@@ -229,8 +284,10 @@ def __init__(self, spec):
229284 def enumerate (self , width ):
230285 for spec in self .spec :
231286 match = SPEC .match (spec )
232- if match :
287+ assert match is not None
288+ if True :
233289 id = match .group ('id' )
290+ assert id is not None
234291 is_vector = id .islower ()
235292 type_ctors = TYPE_ID_LOOKUP [id .lower ()]
236293
@@ -256,19 +313,21 @@ def enumerate(self, width):
256313 scalar = ctor (bitwidth )
257314
258315 if is_vector :
259- yield Vector (scalar , width // bitwidth )
316+ elem = Vector (scalar , width // bitwidth )
260317 else :
261- yield scalar
318+ elem = scalar
319+ yield ptrify (match , elem , width )
262320 bitwidth *= 2
263321 else :
264- print ('Failed to parse: `{}`' .format (spec ), file = sys .stderr )
322+ pass
323+ #print('Failed to parse: `{}`'.format(spec), file=sys.stderr)
265324
266325 def resolve (self , width , zero ):
267326 assert len (self .spec ) == 1
268327 spec = self .spec [0 ]
269328 match = SPEC .match (spec )
270329 if match :
271- id = match .group ('id' )
330+ id = match .group ('id' )
272331 if id is not None :
273332 options = list (self .enumerate (width ))
274333 assert len (options ) == 1
@@ -282,7 +341,7 @@ def resolve(self, width, zero):
282341 force = match .group ('force_width' )
283342 if force is not None :
284343 ret = ret .modify (force , width )
285- return ret
344+ return ptrify ( match , ret , width )
286345 elif spec .startswith ('(' ):
287346 if spec .endswith (')' ):
288347 raise NotImplementedError ()
@@ -291,6 +350,8 @@ def resolve(self, width, zero):
291350 flatten = True
292351 elems = [TypeSpec (subspec ).resolve (width , zero ) for subspec in true_spec .split (',' )]
293352 return Aggregate (flatten , elems )
353+ else :
354+ assert False , 'Failed to resolve: {}' .format (spec )
294355
295356class GenericIntrinsic (object ):
296357 def __init__ (self , platform , intrinsic , widths , llvm_name , ret , args ):
@@ -369,7 +430,10 @@ def parse_args():
369430 ## Type specifier grammar
370431
371432 ```
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
373437
374438 vector := vector_elem width |
375439 vector_elem := 'i' | 'u' | 's' | 'f'
@@ -390,6 +454,18 @@ def parse_args():
390454 number = [0-9]+
391455 ```
392456
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+
393469 ## Vectors
394470
395471 The vector grammar is a pattern describing many possibilities
@@ -454,6 +530,9 @@ def parse_args():
454530 - 'u': force an integer (vector or scalar) to be unsigned (i32x4 -> u32x4)
455531 - 's': force an integer (vector or scalar) to be signed (u32x4 -> i32x4)
456532 - '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)
457536 ''' ))
458537 parser .add_argument ('--format' , choices = FORMATS , required = True ,
459538 help = 'Output format.' )
@@ -502,7 +581,7 @@ def open(self, platform):
502581
503582#![allow(unused_imports)]
504583
505- use {{Intrinsic, i, i_, u, u_, f, v, agg}};
584+ use {{Intrinsic, i, i_, u, u_, f, v, agg, p }};
506585use IntrinsicDef::Named;
507586use rustc::middle::ty;
508587
0 commit comments