Support different scalar integer widths in Rust v. LLVM.
Some x86 C intrinsics are declared to take `int ...` (i.e. exposed in Rust as `i32`), but LLVM implements them by taking `i8` instead.
This commit is contained in:
parent
daf8bdca57
commit
29dcff3aa2
9 changed files with 136 additions and 69 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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}",
|
||||
|
|
|
|||
|
|
@ -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],
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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)) |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue