Skip to content

Commit d12135a

Browse files
committed
Add support for pointers to generator.py.
1 parent 2f77a59 commit d12135a

File tree

7 files changed

+125
-17
lines changed

7 files changed

+125
-17
lines changed

src/etc/platform-intrinsics/generator.py

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
SPEC = 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

2425
class 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+
8389
class 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+
196235
class 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+
222277
class 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

295356
class 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}};
506585
use IntrinsicDef::Named;
507586
use rustc::middle::ty;
508587

src/librustc_platform_intrinsics/aarch64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#![allow(unused_imports)]
1515

16-
use {Intrinsic, i, u, f, v, agg};
16+
use {Intrinsic, i, i_, u, u_, f, v, agg, p};
1717
use IntrinsicDef::Named;
1818
use rustc::middle::ty;
1919

src/librustc_platform_intrinsics/arm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#![allow(unused_imports)]
1515

16-
use {Intrinsic, i, u, f, v, agg};
16+
use {Intrinsic, i, i_, u, u_, f, v, agg, p};
1717
use IntrinsicDef::Named;
1818
use rustc::middle::ty;
1919

src/librustc_platform_intrinsics/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub struct Intrinsic {
3232
pub enum Type {
3333
Integer(/* signed */ bool, u8, /* llvm width */ u8),
3434
Float(u8),
35-
Pointer(Box<Type>),
35+
Pointer(Box<Type>, Option<Box<Type>>, /* const */ bool),
3636
Vector(Box<Type>, u8),
3737
Aggregate(bool, Vec<Type>),
3838
}
@@ -51,6 +51,9 @@ fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) }
5151
fn agg(flatten: bool, types: Vec<Type>) -> Type {
5252
Type::Aggregate(flatten, types)
5353
}
54+
fn p(const_: bool, elem: Type, llvm_elem: Option<Type>) -> Type {
55+
Type::Pointer(Box::new(elem), llvm_elem.map(Box::new), const_)
56+
}
5457

5558
mod x86;
5659
mod arm;

src/librustc_platform_intrinsics/x86.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#![allow(unused_imports)]
1515

16-
use {Intrinsic, i, i_, u, u_, f, v, agg};
16+
use {Intrinsic, i, i_, u, u_, f, v, agg, p};
1717
use IntrinsicDef::Named;
1818
use rustc::middle::ty;
1919

src/librustc_trans/trans/intrinsic.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,14 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
947947
_ => unreachable!()
948948
}
949949
}
950-
Pointer(_) => unimplemented!(),
950+
Pointer(ref t, ref llvm_elem, _const) => {
951+
*any_changes_needed |= llvm_elem.is_some();
952+
953+
let t = llvm_elem.as_ref().unwrap_or(t);
954+
let elem = one(ty_to_type(ccx, t,
955+
any_changes_needed));
956+
vec![elem.ptr_to()]
957+
}
951958
Vector(ref t, length) => {
952959
let elem = one(ty_to_type(ccx, t,
953960
any_changes_needed));
@@ -965,8 +972,9 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
965972
}
966973

967974
// This allows an argument list like `foo, (bar, baz),
968-
// qux` to be converted into `foo, bar, baz, qux`, and
969-
// integer arguments to be truncated as needed.
975+
// qux` to be converted into `foo, bar, baz, qux`, integer
976+
// arguments to be truncated as needed and pointers to be
977+
// cast.
970978
fn modify_as_needed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
971979
t: &intrinsics::Type,
972980
arg_type: Ty<'tcx>,
@@ -991,6 +999,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
991999
})
9921000
.collect()
9931001
}
1002+
intrinsics::Type::Pointer(_, Some(ref llvm_elem), _) => {
1003+
let llvm_elem = one(ty_to_type(bcx.ccx(), llvm_elem, &mut false));
1004+
vec![PointerCast(bcx, llarg,
1005+
llvm_elem.ptr_to())]
1006+
}
9941007
intrinsics::Type::Integer(_, width, llvm_width) if width != llvm_width => {
9951008
// the LLVM intrinsic uses a smaller integer
9961009
// size than the C intrinsic's signature, so

src/librustc_typeck/check/intrinsic.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,20 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
485485
_ => simple_error(&format!("`{}`", t),
486486
&format!("`f{n}`", n = bits)),
487487
},
488-
Pointer(_) => unimplemented!(),
488+
Pointer(ref inner_expected, ref _llvm_type, const_) => {
489+
match t.sty {
490+
ty::TyRawPtr(ty::TypeAndMut { ty, mutbl }) => {
491+
if (mutbl == hir::MutImmutable) != const_ {
492+
simple_error(&format!("`{}`", t),
493+
if const_ {"const pointer"} else {"mut pointer"})
494+
}
495+
match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal,
496+
inner_expected, ty)
497+
}
498+
_ => simple_error(&format!("`{}`", t),
499+
&format!("raw pointer")),
500+
}
501+
}
489502
Vector(ref inner_expected, len) => {
490503
if !t.is_simd() {
491504
simple_error(&format!("non-simd type `{}`", t),

0 commit comments

Comments
 (0)