Skip to content

Commit

Permalink
Support different scalar integer widths in Rust v. LLVM.
Browse files Browse the repository at this point in the history
Some x86 C intrinsics are declared to take `int ...` (i.e. exposed in
Rust as `i32`), but LLVM implements them by taking `i8` instead.
  • Loading branch information
huonw committed Aug 30, 2015
1 parent daf8bdc commit 29dcff3
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 69 deletions.
50 changes: 39 additions & 11 deletions src/etc/platform-intrinsics/generator.py
Expand Up @@ -16,7 +16,8 @@
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+)?)$'
)

Expand Down Expand Up @@ -111,27 +112,39 @@ def type_info(self, platform_info):
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())
Expand Down Expand Up @@ -220,18 +233,28 @@ def enumerate(self, width):
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:
Expand Down Expand Up @@ -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'?
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -474,7 +502,7 @@ def open(self, platform):
#![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;
Expand Down
2 changes: 1 addition & 1 deletion src/etc/platform-intrinsics/x86/avx.json
Expand Up @@ -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}",
Expand Down
14 changes: 14 additions & 0 deletions src/etc/platform-intrinsics/x86/avx2.json
Expand Up @@ -78,6 +78,20 @@
"ret": "i(8-32)",
"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],
Expand Down
4 changes: 2 additions & 2 deletions src/etc/platform-intrinsics/x86/sse41.json
Expand Up @@ -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}",
Expand Down Expand Up @@ -34,7 +34,7 @@
"width": [128],
"llvm": "mpsadbw",
"ret": "u16",
"args": ["u8", "u8", "S32"]
"args": ["u8", "u8", "S32/8"]
},
{
"intrinsic": "_mul_epi32",
Expand Down
28 changes: 14 additions & 14 deletions src/etc/platform-intrinsics/x86/sse42.json
Expand Up @@ -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"]
}
]
}
9 changes: 6 additions & 3 deletions src/librustc_platform_intrinsics/lib.rs
Expand Up @@ -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),
Expand All @@ -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 {
Expand Down

0 comments on commit 29dcff3

Please sign in to comment.