Skip to content

Commit 788c91c

Browse files
committed
Add CI for more platforms
This commit adds CI for a few more targets: * i686-unknown-linux-gnu * arm-unknown-linux-gnueabihf * armv7-unknown-linux-gnueabihf * aarch64-unknown-linux-gnu The CI here is structured around using a Docker container to set up a test environment and then QEMU is used to actually execute code from these platforms. QEMU's emulation actually makes it so we can continue to just use `cargo test`, as processes can be spawned from QEMU like `objdump` and files can be read (for libbacktrace). Ends up being a relatively seamless experience! Note that a number of intrinsics were disabled on i686 because they were failing tests, and otherwise a few ARM touch-ups were made to get tests passing.
1 parent 453e170 commit 788c91c

File tree

18 files changed

+247
-92
lines changed

18 files changed

+247
-92
lines changed

.travis.yml

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
language: rust
22
sudo: false
3+
rust: nightly
34

45
matrix:
56
include:
6-
- rust: nightly
7-
- rust: nightly
8-
os: osx
7+
- env: TARGET=i686-unknown-linux-gnu
8+
- env: TARGET=x86_64-unknown-linux-gnu NO_ADD=1
9+
- env: TARGET=arm-unknown-linux-gnueabihf
10+
- env: TARGET=armv7-unknown-linux-gnueabihf
11+
- env: TARGET=aarch64-unknown-linux-gnu
12+
- os: osx
13+
env: TARGET=x86_64-apple-darwin NO_ADD=1
14+
script: ci/run.sh
15+
16+
install:
17+
- if [ "$NO_ADD" = "" ]; then rustup target add $TARGET; fi
918

1019
script:
11-
- cargo test
12-
- cargo test --release
20+
- cargo generate-lockfile
21+
- ci/run-docker.sh $TARGET
1322

1423
notifications:
1524
email:

assert-instr/src/lib.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ fn disassemble_myself() -> HashMap<String, Vec<Function>> {
5858

5959
parse_otool(&str::from_utf8(&output.stdout).expect("stdout not utf8"))
6060
} else {
61-
let output = Command::new("objdump")
61+
let objdump = env::var("OBJDUMP").unwrap_or("objdump".to_string());
62+
let output = Command::new(objdump)
6263
.arg("--disassemble")
6364
.arg(&me)
6465
.output()
@@ -72,6 +73,13 @@ fn disassemble_myself() -> HashMap<String, Vec<Function>> {
7273

7374
fn parse_objdump(output: &str) -> HashMap<String, Vec<Function>> {
7475
let mut lines = output.lines();
76+
let expected_len = if cfg!(target_arch = "arm") {
77+
8
78+
} else if cfg!(target_arch = "aarch64") {
79+
8
80+
} else {
81+
2
82+
};
7583

7684
for line in output.lines().take(100) {
7785
println!("{}", line);
@@ -97,7 +105,7 @@ fn parse_objdump(output: &str) -> HashMap<String, Vec<Function>> {
97105
let parts = instruction.split_whitespace()
98106
.skip(1)
99107
.skip_while(|s| {
100-
s.len() == 2 && usize::from_str_radix(s, 16).is_ok()
108+
s.len() == expected_len && usize::from_str_radix(s, 16).is_ok()
101109
})
102110
.map(|s| s.to_string())
103111
.collect::<Vec<String>>();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM ubuntu:17.10
2+
RUN apt-get update && apt-get install -y --no-install-recommends \
3+
gcc \
4+
ca-certificates \
5+
libc6-dev \
6+
gcc-aarch64-linux-gnu \
7+
libc6-dev-arm64-cross \
8+
qemu-user \
9+
make \
10+
file
11+
ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
12+
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER="qemu-aarch64 -L /usr/aarch64-linux-gnu" \
13+
OBJDUMP=aarch64-linux-gnu-objdump
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM ubuntu:17.10
2+
RUN apt-get update && apt-get install -y --no-install-recommends \
3+
gcc \
4+
ca-certificates \
5+
libc6-dev \
6+
gcc-arm-linux-gnueabihf \
7+
libc6-dev-armhf-cross \
8+
qemu-user \
9+
make \
10+
file
11+
ENV CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
12+
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER="qemu-arm -L /usr/arm-linux-gnueabihf" \
13+
OBJDUMP=arm-linux-gnueabihf-objdump
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM ubuntu:17.10
2+
RUN apt-get update && apt-get install -y --no-install-recommends \
3+
gcc \
4+
ca-certificates \
5+
libc6-dev \
6+
gcc-arm-linux-gnueabihf \
7+
libc6-dev-armhf-cross \
8+
qemu-user \
9+
make \
10+
file
11+
ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc \
12+
CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_RUNNER="qemu-arm -L /usr/arm-linux-gnueabihf" \
13+
OBJDUMP=arm-linux-gnueabihf-objdump
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM ubuntu:17.04
2+
RUN apt-get update && apt-get install -y --no-install-recommends \
3+
gcc-multilib \
4+
libc6-dev \
5+
file \
6+
make \
7+
ca-certificates
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM ubuntu:17.04
2+
RUN apt-get update && apt-get install -y --no-install-recommends \
3+
gcc \
4+
libc6-dev \
5+
file \
6+
make \
7+
ca-certificates

ci/run-docker.sh

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Small script to run tests for a target (or all targets) inside all the
2+
# respective docker images.
3+
4+
set -ex
5+
6+
run() {
7+
echo $1
8+
docker build -t stdsimd ci/docker/$1
9+
mkdir -p target
10+
docker run \
11+
--user `id -u`:`id -g` \
12+
--rm \
13+
--init \
14+
--volume $HOME/.cargo:/cargo \
15+
--env CARGO_HOME=/cargo \
16+
--volume `rustc --print sysroot`:/rust:ro \
17+
--env TARGET=$1 \
18+
--volume `pwd`:/checkout:ro \
19+
--volume `pwd`/target:/checkout/target \
20+
--workdir /checkout \
21+
stdsimd \
22+
bash \
23+
-c 'PATH=$PATH:/rust/bin exec ci/run.sh $1'
24+
}
25+
26+
if [ -z "$1" ]; then
27+
for d in `ls ci/docker/`; do
28+
run $d
29+
done
30+
else
31+
run $1
32+
fi

ci/run.sh

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/sh
2+
3+
set -ex
4+
5+
cargo test --target $TARGET
6+
cargo test --release --target $TARGET

examples/play.rs

+51-42
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,57 @@
11
#![feature(target_feature)]
22

3-
extern crate stdsimd;
4-
5-
use std::env;
6-
use stdsimd::simd as s;
7-
use stdsimd::vendor;
8-
9-
#[inline(never)]
10-
#[target_feature = "+sse4.2"]
11-
fn index(needle: &str, haystack: &str) -> usize {
12-
assert!(needle.len() <= 16 && haystack.len() <= 16);
13-
14-
let (needle_len, hay_len) = (needle.len(), haystack.len());
15-
16-
let mut needle = needle.to_string().into_bytes();
17-
needle.resize(16, 0);
18-
let vneedle = vendor::__m128i::from(s::u8x16::load(&needle, 0));
19-
20-
let mut haystack = haystack.to_string().into_bytes();
21-
haystack.resize(16, 0);
22-
let vhaystack = vendor::__m128i::from(s::u8x16::load(&haystack, 0));
23-
24-
vendor::_mm_cmpestri(
25-
vneedle, needle_len as i32, vhaystack, hay_len as i32,
26-
vendor::_SIDD_CMP_EQUAL_ORDERED) as usize
3+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
4+
mod example {
5+
6+
extern crate stdsimd;
7+
8+
use std::env;
9+
use self::stdsimd::simd as s;
10+
use self::stdsimd::vendor;
11+
12+
#[inline(never)]
13+
#[target_feature = "+sse4.2"]
14+
fn index(needle: &str, haystack: &str) -> usize {
15+
assert!(needle.len() <= 16 && haystack.len() <= 16);
16+
17+
let (needle_len, hay_len) = (needle.len(), haystack.len());
18+
19+
let mut needle = needle.to_string().into_bytes();
20+
needle.resize(16, 0);
21+
let vneedle = vendor::__m128i::from(s::u8x16::load(&needle, 0));
22+
23+
let mut haystack = haystack.to_string().into_bytes();
24+
haystack.resize(16, 0);
25+
let vhaystack = vendor::__m128i::from(s::u8x16::load(&haystack, 0));
26+
27+
vendor::_mm_cmpestri(
28+
vneedle, needle_len as i32, vhaystack, hay_len as i32,
29+
vendor::_SIDD_CMP_EQUAL_ORDERED) as usize
30+
}
31+
32+
pub fn main() {
33+
// let x0: f64 = env::args().nth(1).unwrap().parse().unwrap();
34+
// let x1: f64 = env::args().nth(2).unwrap().parse().unwrap();
35+
// let x2: f64 = env::args().nth(3).unwrap().parse().unwrap();
36+
// let x3: f64 = env::args().nth(4).unwrap().parse().unwrap();
37+
// let y0: i32 = env::args().nth(5).unwrap().parse().unwrap();
38+
// let y1: i32 = env::args().nth(6).unwrap().parse().unwrap();
39+
// let y2: i32 = env::args().nth(7).unwrap().parse().unwrap();
40+
// let y3: i32 = env::args().nth(8).unwrap().parse().unwrap();
41+
42+
// let a = s::f64x2::new(x0, x1);
43+
// let b = s::f64x2::new(x2, x3);
44+
// let r = s::_mm_cmplt_sd(a, b);
45+
// let r = foobar(a, b);
46+
47+
48+
let needle = env::args().nth(1).unwrap();
49+
let haystack = env::args().nth(2).unwrap();
50+
println!("{:?}", index(&needle, &haystack));
51+
}
2752
}
2853

2954
fn main() {
30-
// let x0: f64 = env::args().nth(1).unwrap().parse().unwrap();
31-
// let x1: f64 = env::args().nth(2).unwrap().parse().unwrap();
32-
// let x2: f64 = env::args().nth(3).unwrap().parse().unwrap();
33-
// let x3: f64 = env::args().nth(4).unwrap().parse().unwrap();
34-
// let y0: i32 = env::args().nth(5).unwrap().parse().unwrap();
35-
// let y1: i32 = env::args().nth(6).unwrap().parse().unwrap();
36-
// let y2: i32 = env::args().nth(7).unwrap().parse().unwrap();
37-
// let y3: i32 = env::args().nth(8).unwrap().parse().unwrap();
38-
39-
// let a = s::f64x2::new(x0, x1);
40-
// let b = s::f64x2::new(x2, x3);
41-
// let r = s::_mm_cmplt_sd(a, b);
42-
// let r = foobar(a, b);
43-
44-
45-
let needle = env::args().nth(1).unwrap();
46-
let haystack = env::args().nth(2).unwrap();
47-
println!("{:?}", index(&needle, &haystack));
55+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
56+
example::main();
4857
}

examples/types.rs

+25-17
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
#![feature(target_feature)]
22

3-
extern crate stdsimd;
3+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
4+
mod example {
5+
extern crate stdsimd;
46

5-
use std::env;
6-
use stdsimd::simd;
7+
use std::env;
8+
use self::stdsimd::simd;
79

8-
#[inline(never)]
9-
#[target_feature = "-sse2"]
10-
fn myop(
11-
(x0, x1, x2, x3): (u64, u64, u64, u64),
12-
(y0, y1, y2, y3): (u64, u64, u64, u64),
13-
) -> (u64, u64, u64, u64) {
14-
let x = simd::u64x4::new(x0, x1, x2, x3);
15-
let y = simd::u64x4::new(y0, y1, y2, y3);
16-
let r = x * y;
17-
(r.extract(0), r.extract(1), r.extract(2), r.extract(3))
10+
#[inline(never)]
11+
#[target_feature = "-sse2"]
12+
fn myop(
13+
(x0, x1, x2, x3): (u64, u64, u64, u64),
14+
(y0, y1, y2, y3): (u64, u64, u64, u64),
15+
) -> (u64, u64, u64, u64) {
16+
let x = simd::u64x4::new(x0, x1, x2, x3);
17+
let y = simd::u64x4::new(y0, y1, y2, y3);
18+
let r = x * y;
19+
(r.extract(0), r.extract(1), r.extract(2), r.extract(3))
20+
}
21+
22+
pub fn main() {
23+
let x = env::args().nth(1).unwrap().parse().unwrap();
24+
let y = env::args().nth(1).unwrap().parse().unwrap();
25+
let r = myop((x, x, x, x), (y, y, y, y));
26+
println!("{:?}", r);
27+
}
1828
}
1929

2030
fn main() {
21-
let x = env::args().nth(1).unwrap().parse().unwrap();
22-
let y = env::args().nth(1).unwrap().parse().unwrap();
23-
let r = myop((x, x, x, x), (y, y, y, y));
24-
println!("{:?}", r);
31+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
32+
example::main();
2533
}

examples/wat.rs

+25-17
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
#![feature(target_feature)]
22

3-
extern crate stdsimd;
3+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
4+
mod example {
5+
extern crate stdsimd;
46

5-
use std::env;
6-
use stdsimd::simd;
7+
use std::env;
8+
use self::stdsimd::simd;
79

8-
#[inline(never)]
9-
#[target_feature = "-sse2"]
10-
fn myop(
11-
(x0, x1, x2, x3): (u64, u64, u64, u64),
12-
(y0, y1, y2, y3): (u64, u64, u64, u64),
13-
) -> (u64, u64, u64, u64) {
14-
let x = simd::u64x4::new(x0, x1, x2, x3);
15-
let y = simd::u64x4::new(y0, y1, y2, y3);
16-
let r = x * y;
17-
(r.extract(0), r.extract(1), r.extract(2), r.extract(3))
10+
#[inline(never)]
11+
#[target_feature = "-sse2"]
12+
fn myop(
13+
(x0, x1, x2, x3): (u64, u64, u64, u64),
14+
(y0, y1, y2, y3): (u64, u64, u64, u64),
15+
) -> (u64, u64, u64, u64) {
16+
let x = simd::u64x4::new(x0, x1, x2, x3);
17+
let y = simd::u64x4::new(y0, y1, y2, y3);
18+
let r = x * y;
19+
(r.extract(0), r.extract(1), r.extract(2), r.extract(3))
20+
}
21+
22+
pub fn main() {
23+
let x = env::args().nth(1).unwrap().parse().unwrap();
24+
let y = env::args().nth(2).unwrap().parse().unwrap();
25+
let r = myop((x, x, x, x), (y, y, y, y));
26+
println!("{:?}", r);
27+
}
1828
}
1929

2030
fn main() {
21-
let x = env::args().nth(1).unwrap().parse().unwrap();
22-
let y = env::args().nth(2).unwrap().parse().unwrap();
23-
let r = myop((x, x, x, x), (y, y, y, y));
24-
println!("{:?}", r);
31+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
32+
example::main();
2533
}

src/arm/v6.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,8 @@
33
//! The reference is [ARMv6-M Architecture Reference
44
//! Manual](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0419c/index.html).
55
6-
/// Reverse the order of the bytes.
7-
#[inline(always)]
8-
#[cfg_attr(test, assert_instr(rev))]
9-
pub fn _rev_u8(x: u8) -> u8 {
10-
x.swap_bytes() as u8
11-
}
6+
#[cfg(test)]
7+
use assert_instr::assert_instr;
128

139
/// Reverse the order of the bytes.
1410
#[inline(always)]

src/arm/v7.rs

+4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
66
pub use super::v6::*;
77

8+
#[cfg(test)]
9+
use assert_instr::assert_instr;
10+
811
/// Count Leading Zeros.
912
#[inline(always)]
1013
#[cfg_attr(test, assert_instr(clz))]
@@ -35,6 +38,7 @@ extern "C" {
3538
/// Reverse the bit order.
3639
#[inline(always)]
3740
#[cfg_attr(test, assert_instr(rbit))]
41+
#[cfg_attr(target_arch = "arm", target_feature = "+v7")]
3842
pub fn _rbit_u32(x: u32) -> u32 {
3943
unsafe { rbit_u32(x as i32) as u32 }
4044
}

0 commit comments

Comments
 (0)