diff options
| -rw-r--r-- | src/etc/platform-intrinsics/generator.py | 50 | ||||
| -rw-r--r-- | src/etc/platform-intrinsics/x86/avx.json | 2 | ||||
| -rw-r--r-- | src/etc/platform-intrinsics/x86/avx2.json | 14 | ||||
| -rw-r--r-- | src/etc/platform-intrinsics/x86/sse41.json | 4 | ||||
| -rw-r--r-- | src/etc/platform-intrinsics/x86/sse42.json | 28 | ||||
| -rwxr-xr-x | src/librustc_platform_intrinsics/lib.rs | 9 | ||||
| -rw-r--r-- | src/librustc_platform_intrinsics/x86.rs | 48 | ||||
| -rw-r--r-- | src/librustc_trans/trans/intrinsic.rs | 47 | ||||
| -rw-r--r-- | src/librustc_typeck/check/intrinsic.rs | 3 |
9 files changed, 136 insertions, 69 deletions
diff --git a/src/etc/platform-intrinsics/generator.py b/src/etc/platform-intrinsics/generator.py index 7f5a737e33e..97b2f57010b 100644 --- a/src/etc/platform-intrinsics/generator.py +++ b/src/etc/platform-intrinsics/generator.py @@ -16,7 +16,8 @@ import re import textwrap SPEC = re.compile( - r'^(?:(?P<id>[iusfIUSF])(?:\((?P<start>\d*)-(?P<end>\d*)\)|(?P<width>\d*))' + + 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+)?)$' ) @@ -111,27 +112,39 @@ class Number(Type): return platform_info.number_type_info(self) class Signed(Number): - def __init__(self, bitwidth): + def __init__(self, bitwidth, llvm_bitwidth = None): Number.__init__(self, bitwidth) + self._llvm_bitwidth = llvm_bitwidth def compiler_ctor(self): - return 'i({})'.format(self.bitwidth()) + if self._llvm_bitwidth is None: + return 'i({})'.format(self.bitwidth()) + else: + return 'i_({}, {})'.format(self.bitwidth(), + self._llvm_bitwidth) def llvm_name(self): - return 'i{}'.format(self.bitwidth()) + bw = self._llvm_bitwidth or self.bitwidth() + return 'i{}'.format(bw) def rust_name(self): return 'i{}'.format(self.bitwidth()) class Unsigned(Number): - def __init__(self, bitwidth): + def __init__(self, bitwidth, llvm_bitwidth = None): Number.__init__(self, bitwidth) + self._llvm_bitwidth = llvm_bitwidth def compiler_ctor(self): - return 'u({})'.format(self.bitwidth()) + if self._llvm_bitwidth is None: + return 'u({})'.format(self.bitwidth()) + else: + return 'u_({}, {})'.format(self.bitwidth(), + self._llvm_bitwidth) def llvm_name(self): - return 'i{}'.format(self.bitwidth()) + bw = self._llvm_bitwidth or self.bitwidth() + return 'i{}'.format(bw) def rust_name(self): return 'u{}'.format(self.bitwidth()) @@ -220,18 +233,28 @@ class TypeSpec(object): id = match.group('id') is_vector = id.islower() type_ctors = TYPE_ID_LOOKUP[id.lower()] + start = match.group('start') if start is not None: end = match.group('end') + llvm_width = None else: start = end = match.group('width') + llvm_width = match.group('llvm_width') start = int(start) end = int(end) bitwidth = start while bitwidth <= end: for ctor in type_ctors: - scalar = ctor(bitwidth) + if llvm_width is not None: + assert not is_vector + llvm_width = int(llvm_width) + assert llvm_width < bitwidth + scalar = ctor(bitwidth, llvm_width) + else: + scalar = ctor(bitwidth) + if is_vector: yield Vector(scalar, width // bitwidth) else: @@ -351,8 +374,9 @@ def parse_args(): vector := vector_elem width | vector_elem := 'i' | 'u' | 's' | 'f' - scalar := scalar_type number + scalar := scalar_type number llvm_width? scalar_type := 'U' | 'S' | 'F' + llvm_width := '/' number aggregate := '(' (type),* ')' 'f'? @@ -387,7 +411,11 @@ def parse_args(): ## Scalars Similar to vectors, but these describe a single concrete type, - not a range. The number is the bitwidth. + not a range. The number is the bitwidth. The optional + `llvm_width` is the bitwidth of the integer that should be + passed to LLVM (by truncating the Rust argument): this only + works with scalar integers and the LLVM width must be smaller + than the Rust width. ### Types @@ -474,7 +502,7 @@ class CompilerDefs(object): #![allow(unused_imports)] -use {{Intrinsic, i, u, f, v, agg}}; +use {{Intrinsic, i, i_, u, u_, f, v, agg}}; use IntrinsicDef::Named; use rustc::middle::ty; diff --git a/src/etc/platform-intrinsics/x86/avx.json b/src/etc/platform-intrinsics/x86/avx.json index 7d6a07f7550..4ac82fb90e9 100644 --- a/src/etc/platform-intrinsics/x86/avx.json +++ b/src/etc/platform-intrinsics/x86/avx.json @@ -13,7 +13,7 @@ "width": [256], "llvm": "dp.ps.256", "ret": "f32", - "args": ["0", "0", "S32"] + "args": ["0", "0", "S32/8"] }, { "intrinsic": "256_hadd_{0.data_type}", diff --git a/src/etc/platform-intrinsics/x86/avx2.json b/src/etc/platform-intrinsics/x86/avx2.json index 8b0e53e48cf..bd260ec02e9 100644 --- a/src/etc/platform-intrinsics/x86/avx2.json +++ b/src/etc/platform-intrinsics/x86/avx2.json @@ -79,6 +79,20 @@ "args": ["0", "0"] }, { + "intrinsic": "256_movemask_epi8", + "width": [256], + "llvm": "pmovmskb", + "ret": "S32", + "args": ["s8"] + }, + { + "intrinsic": "256_mpsadbw_epu8", + "width": [256], + "llvm": "mpsadbw", + "ret": "u16", + "args": ["u8", "u8", "S32/8"] + }, + { "intrinsic": "256_mul_{0.data_type}", "width": [256], "llvm": "pmul{0.data_type_short}.dq", diff --git a/src/etc/platform-intrinsics/x86/sse41.json b/src/etc/platform-intrinsics/x86/sse41.json index 8610dc83bd6..e835320e5cd 100644 --- a/src/etc/platform-intrinsics/x86/sse41.json +++ b/src/etc/platform-intrinsics/x86/sse41.json @@ -6,7 +6,7 @@ "width": [128], "llvm": "dp{0.data_type}", "ret": "f(32-64)", - "args": ["0", "0", "S32"] + "args": ["0", "0", "S32/8"] }, { "intrinsic": "_max_{0.data_type}", @@ -34,7 +34,7 @@ "width": [128], "llvm": "mpsadbw", "ret": "u16", - "args": ["u8", "u8", "S32"] + "args": ["u8", "u8", "S32/8"] }, { "intrinsic": "_mul_epi32", diff --git a/src/etc/platform-intrinsics/x86/sse42.json b/src/etc/platform-intrinsics/x86/sse42.json index e63182d4857..c43ffef0dc5 100644 --- a/src/etc/platform-intrinsics/x86/sse42.json +++ b/src/etc/platform-intrinsics/x86/sse42.json @@ -6,98 +6,98 @@ "width": [128], "llvm": "pcmpestria128", "ret": "S32", - "args": ["s8", "S32", "s8", "S32", "S32"] + "args": ["s8", "S32", "s8", "S32", "S32/8"] }, { "intrinsic": "_cmpestrc", "width": [128], "llvm": "pcmpestric128", "ret": "S32", - "args": ["s8", "S32", "s8", "S32", "S32"] + "args": ["s8", "S32", "s8", "S32", "S32/8"] }, { "intrinsic": "_cmpestri", "width": [128], "llvm": "pcmpestri128", "ret": "S32", - "args": ["s8", "S32", "s8", "S32", "S32"] + "args": ["s8", "S32", "s8", "S32", "S32/8"] }, { "intrinsic": "_cmpestrm", "width": [128], "llvm": "pcmpestrm128", "ret": "s8", - "args": ["s8", "S32", "s8", "S32", "S32"] + "args": ["s8", "S32", "s8", "S32", "S32/8"] }, { "intrinsic": "_cmpestro", "width": [128], "llvm": "pcmpestrio128", "ret": "S32", - "args": ["s8", "S32", "s8", "S32", "S32"] + "args": ["s8", "S32", "s8", "S32", "S32/8"] }, { "intrinsic": "_cmpestrs", "width": [128], "llvm": "pcmpestris128", "ret": "S32", - "args": ["s8", "S32", "s8", "S32", "S32"] + "args": ["s8", "S32", "s8", "S32", "S32/8"] }, { "intrinsic": "_cmpestrz", "width": [128], "llvm": "pcmpestriz128", "ret": "S32", - "args": ["s8", "S32", "s8", "S32", "S32"] + "args": ["s8", "S32", "s8", "S32", "S32/8"] }, { "intrinsic": "_cmpistra", "width": [128], "llvm": "pcmpistria128", "ret": "S32", - "args": ["s8", "s8", "S32"] + "args": ["s8", "s8", "S32/8"] }, { "intrinsic": "_cmpistrc", "width": [128], "llvm": "pcmpistric128", "ret": "S32", - "args": ["s8", "s8", "S32"] + "args": ["s8", "s8", "S32/8"] }, { "intrinsic": "_cmpistri", "width": [128], "llvm": "pcmpistri128", "ret": "S32", - "args": ["s8", "s8", "S32"] + "args": ["s8", "s8", "S32/8"] }, { "intrinsic": "_cmpistrm", "width": [128], "llvm": "pcmpistrm128", "ret": "s8", - "args": ["s8", "s8", "S32"] + "args": ["s8", "s8", "S32/8"] }, { "intrinsic": "_cmpistro", "width": [128], "llvm": "pcmpistrio128", "ret": "S32", - "args": ["s8", "s8", "S32"] + "args": ["s8", "s8", "S32/8"] }, { "intrinsic": "_cmpistrs", "width": [128], "llvm": "pcmpistris128", "ret": "S32", - "args": ["s8", "s8", "S32"] + "args": ["s8", "s8", "S32/8"] }, { "intrinsic": "_cmpistrz", "width": [128], "llvm": "pcmpistriz128", "ret": "S32", - "args": ["s8", "s8", "S32"] + "args": ["s8", "s8", "S32/8"] } ] } diff --git a/src/librustc_platform_intrinsics/lib.rs b/src/librustc_platform_intrinsics/lib.rs index 5eb09aeb0dc..d58feb4611c 100755 --- a/src/librustc_platform_intrinsics/lib.rs +++ b/src/librustc_platform_intrinsics/lib.rs @@ -30,7 +30,7 @@ pub struct Intrinsic { #[derive(Clone, Hash, Eq, PartialEq)] pub enum Type { - Integer(/* signed */ bool, u8), + Integer(/* signed */ bool, u8, /* llvm width */ u8), Float(u8), Pointer(Box<Type>), Vector(Box<Type>, u8), @@ -41,8 +41,11 @@ pub enum IntrinsicDef { Named(&'static str), } -fn i(width: u8) -> Type { Type::Integer(true, width) } -fn u(width: u8) -> Type { Type::Integer(false, width) } +fn i(width: u8) -> Type { Type::Integer(true, width, width) } +fn i_(width: u8, llvm_width: u8) -> Type { Type::Integer(true, width, llvm_width) } +fn u(width: u8) -> Type { Type::Integer(false, width, width) } +#[allow(dead_code)] +fn u_(width: u8, llvm_width: u8) -> Type { Type::Integer(false, width, llvm_width) } fn f(width: u8) -> Type { Type::Float(width) } fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) } fn agg(flatten: bool, types: Vec<Type>) -> Type { diff --git a/src/librustc_platform_intrinsics/x86.rs b/src/librustc_platform_intrinsics/x86.rs index d86afa7f41f..a6fe8aef0b4 100644 --- a/src/librustc_platform_intrinsics/x86.rs +++ b/src/librustc_platform_intrinsics/x86.rs @@ -13,7 +13,7 @@ #![allow(unused_imports)] -use {Intrinsic, i, u, f, v, agg}; +use {Intrinsic, i, i_, u, u_, f, v, agg}; use IntrinsicDef::Named; use rustc::middle::ty; @@ -286,12 +286,12 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> { definition: Named("llvm.x86.ssse3.psign.w.128") }, "_dp_ps" => Intrinsic { - inputs: vec![v(f(32), 4), v(f(32), 4), i(32)], + inputs: vec![v(f(32), 4), v(f(32), 4), i_(32, 8)], output: v(f(32), 4), definition: Named("llvm.x86.sse41.dpps") }, "_dp_pd" => Intrinsic { - inputs: vec![v(f(64), 2), v(f(64), 2), i(32)], + inputs: vec![v(f(64), 2), v(f(64), 2), i_(32, 8)], output: v(f(64), 2), definition: Named("llvm.x86.sse41.dppd") }, @@ -341,7 +341,7 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> { definition: Named("llvm.x86.sse41.phminposuw") }, "_mpsadbw_epu8" => Intrinsic { - inputs: vec![v(u(8), 16), v(u(8), 16), i(32)], + inputs: vec![v(u(8), 16), v(u(8), 16), i_(32, 8)], output: v(u(16), 8), definition: Named("llvm.x86.sse41.mpsadbw") }, @@ -371,72 +371,72 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> { definition: Named("llvm.x86.sse41.ptestz") }, "_cmpestra" => Intrinsic { - inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i(32)], + inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpestria128") }, "_cmpestrc" => Intrinsic { - inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i(32)], + inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpestric128") }, "_cmpestri" => Intrinsic { - inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i(32)], + inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpestri128") }, "_cmpestrm" => Intrinsic { - inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i(32)], + inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i_(32, 8)], output: v(i(8), 16), definition: Named("llvm.x86.sse42.pcmpestrm128") }, "_cmpestro" => Intrinsic { - inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i(32)], + inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpestrio128") }, "_cmpestrs" => Intrinsic { - inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i(32)], + inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpestris128") }, "_cmpestrz" => Intrinsic { - inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i(32)], + inputs: vec![v(i(8), 16), i(32), v(i(8), 16), i(32), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpestriz128") }, "_cmpistra" => Intrinsic { - inputs: vec![v(i(8), 16), v(i(8), 16), i(32)], + inputs: vec![v(i(8), 16), v(i(8), 16), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpistria128") }, "_cmpistrc" => Intrinsic { - inputs: vec![v(i(8), 16), v(i(8), 16), i(32)], + inputs: vec![v(i(8), 16), v(i(8), 16), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpistric128") }, "_cmpistri" => Intrinsic { - inputs: vec![v(i(8), 16), v(i(8), 16), i(32)], + inputs: vec![v(i(8), 16), v(i(8), 16), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpistri128") }, "_cmpistrm" => Intrinsic { - inputs: vec![v(i(8), 16), v(i(8), 16), i(32)], + inputs: vec![v(i(8), 16), v(i(8), 16), i_(32, 8)], output: v(i(8), 16), definition: Named("llvm.x86.sse42.pcmpistrm128") }, "_cmpistro" => Intrinsic { - inputs: vec![v(i(8), 16), v(i(8), 16), i(32)], + inputs: vec![v(i(8), 16), v(i(8), 16), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpistrio128") }, "_cmpistrs" => Intrinsic { - inputs: vec![v(i(8), 16), v(i(8), 16), i(32)], + inputs: vec![v(i(8), 16), v(i(8), 16), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpistris128") }, "_cmpistrz" => Intrinsic { - inputs: vec![v(i(8), 16), v(i(8), 16), i(32)], + inputs: vec![v(i(8), 16), v(i(8), 16), i_(32, 8)], output: i(32), definition: Named("llvm.x86.sse42.pcmpistriz128") }, @@ -451,7 +451,7 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> { definition: Named("llvm.x86.avx.addsub.pd.256") }, "256_dp_ps" => Intrinsic { - inputs: vec![v(f(32), 8), v(f(32), 8), i(32)], + inputs: vec![v(f(32), 8), v(f(32), 8), i_(32, 8)], output: v(f(32), 8), definition: Named("llvm.x86.avx.dp.ps.256") }, @@ -765,6 +765,16 @@ pub fn find<'tcx>(_tcx: &ty::ctxt<'tcx>, name: &str) -> Option<Intrinsic> { output: v(u(32), 8), definition: Named("llvm.x86.avx2.pminu.d") }, + "256_movemask_epi8" => Intrinsic { + inputs: vec![v(i(8), 32)], + output: i(32), + definition: Named("llvm.x86.avx2.pmovmskb") + }, + "256_mpsadbw_epu8" => Intrinsic { + inputs: vec![v(u(8), 32), v(u(8), 32), i_(32, 8)], + output: v(u(16), 16), + definition: Named("llvm.x86.avx2.mpsadbw") + }, "256_mul_epi64" => Intrinsic { inputs: vec![v(i(32), 8), v(i(32), 8)], output: v(i(64), 4), diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 267a8a15f69..b883bad7d41 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -930,10 +930,13 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, x.into_iter().next().unwrap() } fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type, - any_flattened_aggregate: &mut bool) -> Vec<Type> { + any_changes_needed: &mut bool) -> Vec<Type> { use intrinsics::Type::*; match *t { - Integer(_signed, x) => vec![Type::ix(ccx, x as u64)], + Integer(_signed, width, llvm_width) => { + *any_changes_needed |= width != llvm_width; + vec![Type::ix(ccx, llvm_width as u64)] + } Float(x) => { match x { 32 => vec![Type::f32(ccx)], @@ -944,27 +947,28 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, Pointer(_) => unimplemented!(), Vector(ref t, length) => { let elem = one(ty_to_type(ccx, t, - any_flattened_aggregate)); + any_changes_needed)); vec![Type::vector(&elem, length as u64)] } Aggregate(false, _) => unimplemented!(), Aggregate(true, ref contents) => { - *any_flattened_aggregate = true; + *any_changes_needed = true; contents.iter() - .flat_map(|t| ty_to_type(ccx, t, any_flattened_aggregate)) + .flat_map(|t| ty_to_type(ccx, t, any_changes_needed)) .collect() } } } // This allows an argument list like `foo, (bar, baz), - // qux` to be converted into `foo, bar, baz, qux`. - fn flatten_aggregate<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, - t: &intrinsics::Type, - arg_type: Ty<'tcx>, - llarg: ValueRef) - -> Vec<ValueRef> + // qux` to be converted into `foo, bar, baz, qux`, and + // integer arguments to be truncated as needed. + fn modify_as_needed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, + t: &intrinsics::Type, + arg_type: Ty<'tcx>, + llarg: ValueRef) + -> Vec<ValueRef> { match *t { intrinsics::Type::Aggregate(true, ref contents) => { @@ -984,22 +988,28 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }) .collect() } + 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 + // we have to trim it down here. + vec![Trunc(bcx, llarg, Type::ix(bcx.ccx(), llvm_width as u64))] + } _ => vec![llarg], } } - let mut any_flattened_aggregate = false; + let mut any_changes_needed = false; let inputs = intr.inputs.iter() - .flat_map(|t| ty_to_type(ccx, t, &mut any_flattened_aggregate)) + .flat_map(|t| ty_to_type(ccx, t, &mut any_changes_needed)) .collect::<Vec<_>>(); - let mut out_flattening = false; - let outputs = one(ty_to_type(ccx, &intr.output, &mut out_flattening)); + let mut out_changes = false; + let outputs = one(ty_to_type(ccx, &intr.output, &mut out_changes)); // outputting a flattened aggregate is nonsense - assert!(!out_flattening); + assert!(!out_changes); - let llargs = if !any_flattened_aggregate { + let llargs = if !any_changes_needed { // no aggregates to flatten, so no change needed llargs } else { @@ -1009,9 +1019,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, intr.inputs.iter() .zip(&llargs) .zip(&arg_tys) - .flat_map(|((t, llarg), ty)| flatten_aggregate(bcx, t, ty, *llarg)) + .flat_map(|((t, llarg), ty)| modify_as_needed(bcx, t, ty, *llarg)) .collect() }; + assert_eq!(inputs.len(), llargs.len()); match intr.definition { intrinsics::IntrinsicDef::Named(name) => { diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 74a1926916b..4bca474f922 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -456,7 +456,8 @@ fn match_intrinsic_type_to_type<'tcx, 'a>( }; match *expected { - Integer(signed, bits) => match (signed, bits, &t.sty) { + // (The width we pass to LLVM doesn't concern the type checker.) + Integer(signed, bits, _llvm_width) => match (signed, bits, &t.sty) { (true, 8, &ty::TyInt(ast::TyI8)) | (false, 8, &ty::TyUint(ast::TyU8)) | (true, 16, &ty::TyInt(ast::TyI16)) | (false, 16, &ty::TyUint(ast::TyU16)) | (true, 32, &ty::TyInt(ast::TyI32)) | (false, 32, &ty::TyUint(ast::TyU32)) | |
