]> git.lizzy.rs Git - rust.git/commitdiff
Add support for pointers to generator.py.
authorHuon Wilson <dbau.pp+github@gmail.com>
Wed, 2 Sep 2015 20:59:35 +0000 (13:59 -0700)
committerHuon Wilson <dbau.pp+github@gmail.com>
Fri, 4 Sep 2015 16:14:12 +0000 (09:14 -0700)
src/etc/platform-intrinsics/generator.py
src/librustc_platform_intrinsics/aarch64.rs
src/librustc_platform_intrinsics/arm.rs
src/librustc_platform_intrinsics/lib.rs
src/librustc_platform_intrinsics/x86.rs
src/librustc_trans/trans/intrinsic.rs
src/librustc_typeck/check/intrinsic.rs

index 97b2f57010b97fcfcdb66c2ac1a837a37e89cb81..bc1d428fee85696cfaf33cc296d7512fe222badc 100644 (file)
@@ -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;
 
index 1f581d8ce855aa4995d84e26d82100d1266a5d67..c90d6b3816ae3e95dd19ee409854643bc8583ec0 100644 (file)
@@ -13,7 +13,7 @@
 
 #![allow(unused_imports)]
 
-use {Intrinsic, i, u, f, v, agg};
+use {Intrinsic, i, i_, u, u_, f, v, agg, p};
 use IntrinsicDef::Named;
 use rustc::middle::ty;
 
index 8ea725ee95df8bb3a9e64975948d870873172dd8..89b147027b5e857b7e141f74dc49988ab3f29b4e 100644 (file)
@@ -13,7 +13,7 @@
 
 #![allow(unused_imports)]
 
-use {Intrinsic, i, u, f, v, agg};
+use {Intrinsic, i, i_, u, u_, f, v, agg, p};
 use IntrinsicDef::Named;
 use rustc::middle::ty;
 
index 1727347ef7bd5bc5a9a2b588a2a70fce7ed4e2f5..8c8beb031ebad111b2756589b2557d5d71d5fff5 100755 (executable)
@@ -32,7 +32,7 @@ pub struct Intrinsic {
 pub enum Type {
     Integer(/* signed */ bool, u8, /* llvm width */ u8),
     Float(u8),
-    Pointer(Box<Type>),
+    Pointer(Box<Type>, Option<Box<Type>>, /* const */ bool),
     Vector(Box<Type>, u8),
     Aggregate(bool, Vec<Type>),
 }
@@ -51,6 +51,9 @@ fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) }
 fn agg(flatten: bool, types: Vec<Type>) -> Type {
     Type::Aggregate(flatten, types)
 }
+fn p(const_: bool, elem: Type, llvm_elem: Option<Type>) -> Type {
+    Type::Pointer(Box::new(elem), llvm_elem.map(Box::new), const_)
+}
 
 mod x86;
 mod arm;
index 64c31ccb50d4ae4206a82f12c5efa21ffe508f84..661603866ae02b338bf0be7e59f4e21e427d9da1 100644 (file)
@@ -13,7 +13,7 @@
 
 #![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;
 
index abe72aed323f2d4807f3f260480bb19d67671b65..c2dee20b3bb9367d270259355206b404ce8be449 100644 (file)
@@ -947,7 +947,14 @@ fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type,
                             _ => unreachable!()
                         }
                     }
-                    Pointer(_) => unimplemented!(),
+                    Pointer(ref t, ref llvm_elem, _const) => {
+                        *any_changes_needed |= llvm_elem.is_some();
+
+                        let t = llvm_elem.as_ref().unwrap_or(t);
+                        let elem = one(ty_to_type(ccx, t,
+                                                  any_changes_needed));
+                        vec![elem.ptr_to()]
+                    }
                     Vector(ref t, length) => {
                         let elem = one(ty_to_type(ccx, t,
                                                   any_changes_needed));
@@ -965,8 +972,9 @@ fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type,
             }
 
             // This allows an argument list like `foo, (bar, baz),
-            // qux` to be converted into `foo, bar, baz, qux`, and
-            // integer arguments to be truncated as needed.
+            // qux` to be converted into `foo, bar, baz, qux`, integer
+            // arguments to be truncated as needed and pointers to be
+            // cast.
             fn modify_as_needed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                             t: &intrinsics::Type,
                                             arg_type: Ty<'tcx>,
@@ -991,6 +999,11 @@ fn modify_as_needed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                             })
                             .collect()
                     }
+                    intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => {
+                        let llvm_elem = one(ty_to_type(bcx.ccx(), llvm_elem, &mut false));
+                        vec![PointerCast(bcx, llarg,
+                                         llvm_elem.ptr_to())]
+                    }
                     intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
                         // the LLVM intrinsic uses a smaller integer
                         // size than the C intrinsic's signature, so
index 0c8bdc0ee04a3a59225463ed67099092f12e6b03..54f6ec0f0eda4614e945871978d0bc9992cef1e9 100644 (file)
@@ -485,7 +485,20 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
             _ => simple_error(&format!("`{}`", t),
                               &format!("`f{n}`", n = bits)),
         },
-        Pointer(_) => unimplemented!(),
+        Pointer(ref inner_expected, ref _llvm_type, const_) => {
+            match t.sty {
+                ty::TyRawPtr(ty::TypeAndMut { ty, mutbl }) => {
+                    if (mutbl == hir::MutImmutable) != const_ {
+                        simple_error(&format!("`{}`", t),
+                                     if const_ {"const pointer"} else {"mut pointer"})
+                    }
+                    match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal,
+                                                 inner_expected, ty)
+                }
+                _ => simple_error(&format!("`{}`", t),
+                                  &format!("raw pointer")),
+            }
+        }
         Vector(ref inner_expected, len) => {
             if !t.is_simd() {
                 simple_error(&format!("non-simd type `{}`", t),