Skip to content

Commit 29dcff3

Browse files
committed
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.
1 parent daf8bdc commit 29dcff3

File tree

9 files changed

+136
-69
lines changed

9 files changed

+136
-69
lines changed

src/etc/platform-intrinsics/generator.py

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
import textwrap
1717

1818
SPEC = re.compile(
19-
r'^(?:(?P<id>[iusfIUSF])(?:\((?P<start>\d*)-(?P<end>\d*)\)|(?P<width>\d*))' +
19+
r'^(?:(?P<id>[iusfIUSF])(?:\((?P<start>\d+)-(?P<end>\d+)\)|'
20+
r'(?P<width>\d+)(:?/(?P<llvm_width>\d+))?)'
2021
r'|(?P<reference>\d+)(?P<modifiers>[vShdnwus]*)(?P<force_width>x\d+)?)$'
2122
)
2223

@@ -111,27 +112,39 @@ def type_info(self, platform_info):
111112
return platform_info.number_type_info(self)
112113

113114
class Signed(Number):
114-
def __init__(self, bitwidth):
115+
def __init__(self, bitwidth, llvm_bitwidth = None):
115116
Number.__init__(self, bitwidth)
117+
self._llvm_bitwidth = llvm_bitwidth
116118

117119
def compiler_ctor(self):
118-
return 'i({})'.format(self.bitwidth())
120+
if self._llvm_bitwidth is None:
121+
return 'i({})'.format(self.bitwidth())
122+
else:
123+
return 'i_({}, {})'.format(self.bitwidth(),
124+
self._llvm_bitwidth)
119125

120126
def llvm_name(self):
121-
return 'i{}'.format(self.bitwidth())
127+
bw = self._llvm_bitwidth or self.bitwidth()
128+
return 'i{}'.format(bw)
122129

123130
def rust_name(self):
124131
return 'i{}'.format(self.bitwidth())
125132

126133
class Unsigned(Number):
127-
def __init__(self, bitwidth):
134+
def __init__(self, bitwidth, llvm_bitwidth = None):
128135
Number.__init__(self, bitwidth)
136+
self._llvm_bitwidth = llvm_bitwidth
129137

130138
def compiler_ctor(self):
131-
return 'u({})'.format(self.bitwidth())
139+
if self._llvm_bitwidth is None:
140+
return 'u({})'.format(self.bitwidth())
141+
else:
142+
return 'u_({}, {})'.format(self.bitwidth(),
143+
self._llvm_bitwidth)
132144

133145
def llvm_name(self):
134-
return 'i{}'.format(self.bitwidth())
146+
bw = self._llvm_bitwidth or self.bitwidth()
147+
return 'i{}'.format(bw)
135148

136149
def rust_name(self):
137150
return 'u{}'.format(self.bitwidth())
@@ -220,18 +233,28 @@ def enumerate(self, width):
220233
id = match.group('id')
221234
is_vector = id.islower()
222235
type_ctors = TYPE_ID_LOOKUP[id.lower()]
236+
223237
start = match.group('start')
224238
if start is not None:
225239
end = match.group('end')
240+
llvm_width = None
226241
else:
227242
start = end = match.group('width')
243+
llvm_width = match.group('llvm_width')
228244
start = int(start)
229245
end = int(end)
230246

231247
bitwidth = start
232248
while bitwidth <= end:
233249
for ctor in type_ctors:
234-
scalar = ctor(bitwidth)
250+
if llvm_width is not None:
251+
assert not is_vector
252+
llvm_width = int(llvm_width)
253+
assert llvm_width < bitwidth
254+
scalar = ctor(bitwidth, llvm_width)
255+
else:
256+
scalar = ctor(bitwidth)
257+
235258
if is_vector:
236259
yield Vector(scalar, width // bitwidth)
237260
else:
@@ -351,8 +374,9 @@ def parse_args():
351374
vector := vector_elem width |
352375
vector_elem := 'i' | 'u' | 's' | 'f'
353376
354-
scalar := scalar_type number
377+
scalar := scalar_type number llvm_width?
355378
scalar_type := 'U' | 'S' | 'F'
379+
llvm_width := '/' number
356380
357381
aggregate := '(' (type),* ')' 'f'?
358382
@@ -387,7 +411,11 @@ def parse_args():
387411
## Scalars
388412
389413
Similar to vectors, but these describe a single concrete type,
390-
not a range. The number is the bitwidth.
414+
not a range. The number is the bitwidth. The optional
415+
`llvm_width` is the bitwidth of the integer that should be
416+
passed to LLVM (by truncating the Rust argument): this only
417+
works with scalar integers and the LLVM width must be smaller
418+
than the Rust width.
391419
392420
### Types
393421
@@ -474,7 +502,7 @@ def open(self, platform):
474502
475503
#![allow(unused_imports)]
476504
477-
use {{Intrinsic, i, u, f, v, agg}};
505+
use {{Intrinsic, i, i_, u, u_, f, v, agg}};
478506
use IntrinsicDef::Named;
479507
use rustc::middle::ty;
480508

src/etc/platform-intrinsics/x86/avx.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"width": [256],
1414
"llvm": "dp.ps.256",
1515
"ret": "f32",
16-
"args": ["0", "0", "S32"]
16+
"args": ["0", "0", "S32/8"]
1717
},
1818
{
1919
"intrinsic": "256_hadd_{0.data_type}",

src/etc/platform-intrinsics/x86/avx2.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@
7878
"ret": "i(8-32)",
7979
"args": ["0", "0"]
8080
},
81+
{
82+
"intrinsic": "256_movemask_epi8",
83+
"width": [256],
84+
"llvm": "pmovmskb",
85+
"ret": "S32",
86+
"args": ["s8"]
87+
},
88+
{
89+
"intrinsic": "256_mpsadbw_epu8",
90+
"width": [256],
91+
"llvm": "mpsadbw",
92+
"ret": "u16",
93+
"args": ["u8", "u8", "S32/8"]
94+
},
8195
{
8296
"intrinsic": "256_mul_{0.data_type}",
8397
"width": [256],

src/etc/platform-intrinsics/x86/sse41.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"width": [128],
77
"llvm": "dp{0.data_type}",
88
"ret": "f(32-64)",
9-
"args": ["0", "0", "S32"]
9+
"args": ["0", "0", "S32/8"]
1010
},
1111
{
1212
"intrinsic": "_max_{0.data_type}",
@@ -34,7 +34,7 @@
3434
"width": [128],
3535
"llvm": "mpsadbw",
3636
"ret": "u16",
37-
"args": ["u8", "u8", "S32"]
37+
"args": ["u8", "u8", "S32/8"]
3838
},
3939
{
4040
"intrinsic": "_mul_epi32",

src/etc/platform-intrinsics/x86/sse42.json

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,98 +6,98 @@
66
"width": [128],
77
"llvm": "pcmpestria128",
88
"ret": "S32",
9-
"args": ["s8", "S32", "s8", "S32", "S32"]
9+
"args": ["s8", "S32", "s8", "S32", "S32/8"]
1010
},
1111
{
1212
"intrinsic": "_cmpestrc",
1313
"width": [128],
1414
"llvm": "pcmpestric128",
1515
"ret": "S32",
16-
"args": ["s8", "S32", "s8", "S32", "S32"]
16+
"args": ["s8", "S32", "s8", "S32", "S32/8"]
1717
},
1818
{
1919
"intrinsic": "_cmpestri",
2020
"width": [128],
2121
"llvm": "pcmpestri128",
2222
"ret": "S32",
23-
"args": ["s8", "S32", "s8", "S32", "S32"]
23+
"args": ["s8", "S32", "s8", "S32", "S32/8"]
2424
},
2525
{
2626
"intrinsic": "_cmpestrm",
2727
"width": [128],
2828
"llvm": "pcmpestrm128",
2929
"ret": "s8",
30-
"args": ["s8", "S32", "s8", "S32", "S32"]
30+
"args": ["s8", "S32", "s8", "S32", "S32/8"]
3131
},
3232
{
3333
"intrinsic": "_cmpestro",
3434
"width": [128],
3535
"llvm": "pcmpestrio128",
3636
"ret": "S32",
37-
"args": ["s8", "S32", "s8", "S32", "S32"]
37+
"args": ["s8", "S32", "s8", "S32", "S32/8"]
3838
},
3939
{
4040
"intrinsic": "_cmpestrs",
4141
"width": [128],
4242
"llvm": "pcmpestris128",
4343
"ret": "S32",
44-
"args": ["s8", "S32", "s8", "S32", "S32"]
44+
"args": ["s8", "S32", "s8", "S32", "S32/8"]
4545
},
4646
{
4747
"intrinsic": "_cmpestrz",
4848
"width": [128],
4949
"llvm": "pcmpestriz128",
5050
"ret": "S32",
51-
"args": ["s8", "S32", "s8", "S32", "S32"]
51+
"args": ["s8", "S32", "s8", "S32", "S32/8"]
5252
},
5353
{
5454
"intrinsic": "_cmpistra",
5555
"width": [128],
5656
"llvm": "pcmpistria128",
5757
"ret": "S32",
58-
"args": ["s8", "s8", "S32"]
58+
"args": ["s8", "s8", "S32/8"]
5959
},
6060
{
6161
"intrinsic": "_cmpistrc",
6262
"width": [128],
6363
"llvm": "pcmpistric128",
6464
"ret": "S32",
65-
"args": ["s8", "s8", "S32"]
65+
"args": ["s8", "s8", "S32/8"]
6666
},
6767
{
6868
"intrinsic": "_cmpistri",
6969
"width": [128],
7070
"llvm": "pcmpistri128",
7171
"ret": "S32",
72-
"args": ["s8", "s8", "S32"]
72+
"args": ["s8", "s8", "S32/8"]
7373
},
7474
{
7575
"intrinsic": "_cmpistrm",
7676
"width": [128],
7777
"llvm": "pcmpistrm128",
7878
"ret": "s8",
79-
"args": ["s8", "s8", "S32"]
79+
"args": ["s8", "s8", "S32/8"]
8080
},
8181
{
8282
"intrinsic": "_cmpistro",
8383
"width": [128],
8484
"llvm": "pcmpistrio128",
8585
"ret": "S32",
86-
"args": ["s8", "s8", "S32"]
86+
"args": ["s8", "s8", "S32/8"]
8787
},
8888
{
8989
"intrinsic": "_cmpistrs",
9090
"width": [128],
9191
"llvm": "pcmpistris128",
9292
"ret": "S32",
93-
"args": ["s8", "s8", "S32"]
93+
"args": ["s8", "s8", "S32/8"]
9494
},
9595
{
9696
"intrinsic": "_cmpistrz",
9797
"width": [128],
9898
"llvm": "pcmpistriz128",
9999
"ret": "S32",
100-
"args": ["s8", "s8", "S32"]
100+
"args": ["s8", "s8", "S32/8"]
101101
}
102102
]
103103
}

src/librustc_platform_intrinsics/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub struct Intrinsic {
3030

3131
#[derive(Clone, Hash, Eq, PartialEq)]
3232
pub enum Type {
33-
Integer(/* signed */ bool, u8),
33+
Integer(/* signed */ bool, u8, /* llvm width */ u8),
3434
Float(u8),
3535
Pointer(Box<Type>),
3636
Vector(Box<Type>, u8),
@@ -41,8 +41,11 @@ pub enum IntrinsicDef {
4141
Named(&'static str),
4242
}
4343

44-
fn i(width: u8) -> Type { Type::Integer(true, width) }
45-
fn u(width: u8) -> Type { Type::Integer(false, width) }
44+
fn i(width: u8) -> Type { Type::Integer(true, width, width) }
45+
fn i_(width: u8, llvm_width: u8) -> Type { Type::Integer(true, width, llvm_width) }
46+
fn u(width: u8) -> Type { Type::Integer(false, width, width) }
47+
#[allow(dead_code)]
48+
fn u_(width: u8, llvm_width: u8) -> Type { Type::Integer(false, width, llvm_width) }
4649
fn f(width: u8) -> Type { Type::Float(width) }
4750
fn v(x: Type, length: u8) -> Type { Type::Vector(Box::new(x), length) }
4851
fn agg(flatten: bool, types: Vec<Type>) -> Type {

0 commit comments

Comments
 (0)