mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +00:00
Add support for pointers to generator.py.
This commit is contained in:
parent
2f77a59d16
commit
d12135a70d
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -947,7 +947,14 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
_ => 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 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
}
|
||||
|
||||
// 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 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut 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
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user