Separate integers into signed and unsigned.

This is necessary to reflect the ARM APIs accurately, since some
functions explicitly take an unsigned parameter and a signed one, of the
same integer shape, so the no-duplicates check will fail unless we
distinguish.
This commit is contained in:
Huon Wilson 2015-08-28 16:32:25 -07:00
parent f578735750
commit b03ca7f805
4 changed files with 30 additions and 16 deletions

View file

@ -30,7 +30,7 @@ pub struct Intrinsic {
#[derive(Clone, Hash, Eq, PartialEq)]
pub enum Type {
Integer(u8),
Integer(/* signed */ bool, u8),
Float(u8),
Pointer(Box<Type>),
Vector(Box<Type>, u8),
@ -40,7 +40,8 @@ pub enum IntrinsicDef {
Named(&'static str),
}
fn i(width: u8) -> Type { Type::Integer(width) }
fn i(width: u8) -> Type { Type::Integer(true, width) }
fn u(width: u8) -> Type { Type::Integer(false, width) }
fn f(width: u8) -> Type { Type::Float(width) }
fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) }

View file

@ -927,7 +927,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
fn ty_to_type(ccx: &CrateContext, t: &intrinsics::Type) -> Type {
use intrinsics::Type::*;
match *t {
Integer(x) => Type::ix(ccx, x as u64),
Integer(_signed, x) => Type::ix(ccx, x as u64),
Float(x) => {
match x {
32 => Type::f32(ccx),

View file

@ -456,13 +456,15 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
};
match *expected {
Integer(bits) => match (bits, &t.sty) {
(8, &ty::TyInt(ast::TyI8)) | (8, &ty::TyUint(ast::TyU8)) |
(16, &ty::TyInt(ast::TyI16)) | (16, &ty::TyUint(ast::TyU16)) |
(32, &ty::TyInt(ast::TyI32)) | (32, &ty::TyUint(ast::TyU32)) |
(64, &ty::TyInt(ast::TyI64)) | (64, &ty::TyUint(ast::TyU64)) => {},
Integer(signed, bits) => 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)) |
(true, 64, &ty::TyInt(ast::TyI64)) | (false, 64, &ty::TyUint(ast::TyU64)) => {},
_ => simple_error(&format!("`{}`", t),
&format!("`i{n}` or `u{n}`", n = bits)),
&format!("`{}{n}`",
if signed {"i"} else {"u"},
n = bits)),
},
Float(bits) => match (bits, &t.sty) {
(32, &ty::TyFloat(ast::TyF32)) |

View file

@ -25,27 +25,38 @@ struct f32x4(f32, f32, f32, f32);
#[repr(simd)]
struct i64x2(i64, i64);
// signed vs. unsigned doesn't matter
mod i {
use i16x8;
// correct signatures work well
mod right {
use {i16x8, u16x8};
extern "platform-intrinsic" {
fn x86_mm_adds_epi16(x: i16x8, y: i16x8) -> i16x8;
fn x86_mm_adds_epu16(x: u16x8, y: u16x8) -> u16x8;
}
}
mod u {
use u16x8;
// but incorrect ones don't.
mod signedness {
use {i16x8, u16x8};
// signedness matters
extern "platform-intrinsic" {
fn x86_mm_adds_epi16(x: u16x8, y: u16x8) -> u16x8;
//~^ ERROR intrinsic argument 1 has wrong type
//~^^ ERROR intrinsic argument 2 has wrong type
//~^^^ ERROR intrinsic return value has wrong type
fn x86_mm_adds_epu16(x: i16x8, y: i16x8) -> i16x8;
//~^ ERROR intrinsic argument 1 has wrong type
//~^^ ERROR intrinsic argument 2 has wrong type
//~^^^ ERROR intrinsic return value has wrong type
}
}
// but lengths do
// as do lengths
extern "platform-intrinsic" {
fn x86_mm_adds_epi16(x: i8x16, y: i32x4) -> i64x2;
//~^ ERROR intrinsic argument 1 has wrong type
//~^^ ERROR intrinsic argument 2 has wrong type
//~^^^ ERROR intrinsic return value has wrong type
}
// and so does int vs. float
// and so does int vs. float:
extern "platform-intrinsic" {
fn x86_mm_max_ps(x: i32x4, y: i32x4) -> i32x4;
//~^ ERROR intrinsic argument 1 has wrong type