about summary refs log tree commit diff
path: root/src/etc
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2015-09-02 13:59:35 -0700
committerHuon Wilson <dbau.pp+github@gmail.com>2015-09-04 09:14:12 -0700
commitd12135a70de99e1cf86e3147379f4eb0678cd97c (patch)
treea99d368c92bd131a72fee9d0945a28a507f54f64 /src/etc
parent2f77a59d1611f58efa8890e935bec271032cd235 (diff)
Add support for pointers to generator.py.
Diffstat (limited to 'src/etc')
-rw-r--r--src/etc/platform-intrinsics/generator.py97
1 files changed, 88 insertions, 9 deletions
diff --git a/src/etc/platform-intrinsics/generator.py b/src/etc/platform-intrinsics/generator.py
index 97b2f57010b..bc1d428fee8 100644
--- a/src/etc/platform-intrinsics/generator.py
+++ b/src/etc/platform-intrinsics/generator.py
@@ -18,7 +18,8 @@ import textwrap
 SPEC = re.compile(
     r'^(?:(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
     r'(?P<width>\d+)(:?/(?P<llvm_width>\d+))?)'
-    r'|(?P<reference>\d+)(?P<modifiers>[vShdnwus]*)(?P<force_width>x\d+)?)$'
+    r'|(?P<reference>\d+)(?P<modifiers>[vShdnwusDMC]*)(?P<force_width>x\d+)?)'
+    r'(?:(?P<pointer>Pm|Pc)(?P<llvm_pointer>/.*)?)?$'
 )
 
 class PlatformInfo(object):
@@ -80,6 +81,11 @@ class PlatformTypeInfo(object):
         props.update(width_info)
         return PlatformTypeInfo('v{}{}'.format(length, self.llvm_name), props)
 
+    def pointer(self):
+        return PlatformTypeInfo('p0{}'.format(self.llvm_name), self.properties)
+
+BITWIDTH_POINTER = '<pointer>'
+
 class Type(object):
     def __init__(self, bitwidth):
         self._bitwidth = bitwidth
@@ -193,6 +199,39 @@ class Vector(Type):
         return elem_info.vectorize(self._length,
                                    platform_info.width_info(self.bitwidth()))
 
+class Pointer(Type):
+    def __init__(self, elem, llvm_elem, const):
+        self._elem = elem;
+        self._llvm_elem = llvm_elem
+        self._const = const
+        Type.__init__(self, BITWIDTH_POINTER)
+
+    def modify(self, spec, width):
+        if spec == 'D':
+            return self._elem
+        elif spec == 'M':
+            return Pointer(self._elem, self._llvm_elem, False)
+        elif spec == 'C':
+            return Pointer(self._elem, self._llvm_elem, True)
+        else:
+            return Pointer(self._elem.modify(spec, width), self._llvm_elem, self._const)
+
+    def compiler_ctor(self):
+        if self._llvm_elem is None:
+            llvm_elem = 'None'
+        else:
+            llvm_elem = 'Some({})'.format(self._llvm_elem.compiler_ctor())
+        return 'p({}, {}, {})'.format('true' if self._const else 'false',
+                                      self._elem.compiler_ctor(),
+                                      llvm_elem)
+
+    def rust_name(self):
+        return '*{} {}'.format('const' if self._const else 'mut',
+                               self._elem.rust_name())
+
+    def type_info(self, platform_info):
+        return self._elem.type_info(platform_info).pointer()
+
 class Aggregate(Type):
     def __init__(self, flatten, elems):
         self._flatten = flatten
@@ -219,6 +258,22 @@ TYPE_ID_LOOKUP = {'i': [Signed, Unsigned],
                   'u': [Unsigned],
                   'f': [Float]}
 
+def ptrify(match, elem, width):
+    ptr = match.group('pointer')
+    if ptr is None:
+        return elem
+    else:
+        llvm_ptr = match.group('llvm_pointer')
+        if llvm_ptr is None:
+            llvm_elem = None
+        else:
+            assert llvm_ptr.startswith('/')
+            options = list(TypeSpec(llvm_ptr[1:]).enumerate(width))
+            assert len(options) == 1
+            llvm_elem = options[0]
+        assert ptr in ('Pc', 'Pm')
+        return Pointer(elem, llvm_elem, ptr == 'Pc')
+
 class TypeSpec(object):
     def __init__(self, spec):
         if not isinstance(spec, list):
@@ -229,8 +284,10 @@ class TypeSpec(object):
     def enumerate(self, width):
         for spec in self.spec:
             match = SPEC.match(spec)
-            if match:
+            assert match is not None
+            if True:
                 id = match.group('id')
+                assert id is not None
                 is_vector = id.islower()
                 type_ctors = TYPE_ID_LOOKUP[id.lower()]
 
@@ -256,19 +313,21 @@ class TypeSpec(object):
                             scalar = ctor(bitwidth)
 
                         if is_vector:
-                            yield Vector(scalar, width // bitwidth)
+                            elem = Vector(scalar, width // bitwidth)
                         else:
-                            yield scalar
+                            elem = scalar
+                        yield ptrify(match, elem, width)
                     bitwidth *= 2
             else:
-                print('Failed to parse: `{}`'.format(spec), file=sys.stderr)
+                pass
+                #print('Failed to parse: `{}`'.format(spec), file=sys.stderr)
 
     def resolve(self, width, zero):
         assert len(self.spec) == 1
         spec = self.spec[0]
         match = SPEC.match(spec)
         if match:
-            id  = match.group('id')
+            id = match.group('id')
             if id is not None:
                 options = list(self.enumerate(width))
                 assert len(options) == 1
@@ -282,7 +341,7 @@ class TypeSpec(object):
             force = match.group('force_width')
             if force is not None:
                 ret = ret.modify(force, width)
-            return ret
+            return ptrify(match, ret, width)
         elif spec.startswith('('):
             if spec.endswith(')'):
                 raise NotImplementedError()
@@ -291,6 +350,8 @@ class TypeSpec(object):
                 flatten = True
             elems = [TypeSpec(subspec).resolve(width, zero) for subspec in true_spec.split(',')]
             return Aggregate(flatten, elems)
+        else:
+            assert False, 'Failed to resolve: {}'.format(spec)
 
 class GenericIntrinsic(object):
     def __init__(self, platform, intrinsic, widths, llvm_name, ret, args):
@@ -369,7 +430,10 @@ def parse_args():
         ## Type specifier grammar
 
         ```
-        type := vector | scalar | aggregate | reference
+        type := ( vector | scalar | aggregate | reference ) pointer?
+
+        pointer := 'Pm' llvm_pointer? | 'Pc' llvm_pointer?
+        llvm_pointer := '/' type
 
         vector := vector_elem width |
         vector_elem := 'i' | 'u' | 's' | 'f'
@@ -390,6 +454,18 @@ def parse_args():
         number = [0-9]+
         ```
 
+        ## Pointers
+
+        Pointers can be created to any type. The `m` vs. `c` chooses
+        mut vs. const. e.g. `S32Pm` corresponds to `*mut i32`, and
+        `i32Pc` corresponds (with width 128) to `*const i8x16`,
+        `*const u32x4`, etc.
+
+        The type after the `/` (optional) represents the type used
+        internally to LLVM, e.g. `S32pm/S8` is exposed as `*mut i32`
+        in Rust, but is `i8*` in LLVM. (This defaults to the main
+        type).
+
         ## Vectors
 
         The vector grammar is a pattern describing many possibilities
@@ -454,6 +530,9 @@ def parse_args():
         - 'u': force an integer (vector or scalar) to be unsigned (i32x4 -> u32x4)
         - 's': force an integer (vector or scalar) to be signed (u32x4 -> i32x4)
         - 'x' number: force the type to be a vector of bitwidth `number`.
+        - 'D': dereference a pointer (*mut u32 -> u32)
+        - 'C': make a pointer const (*mut u32 -> *const u32)
+        - 'M': make a pointer mut (*const u32 -> *mut u32)
         '''))
     parser.add_argument('--format', choices=FORMATS, required=True,
                         help = 'Output format.')
@@ -502,7 +581,7 @@ class CompilerDefs(object):
 
 #![allow(unused_imports)]
 
-use {{Intrinsic, i, i_, u, u_, f, v, agg}};
+use {{Intrinsic, i, i_, u, u_, f, v, agg, p}};
 use IntrinsicDef::Named;
 use rustc::middle::ty;