Get lightbeam compiling on stable Rust (#2370)

This will hopefully remove a small thorn in our side with periodic
nightly breakage due to nightly features changing. This commit moves
lightbeam to stable Rust, swapping out `staticvec` for `arrayvec` and
otherwise updating some dependencies (namely `dynasm`) to compile with
stable.

This then also updates CI appropriately to not use a pinned nightly and
instead us a floating `nightly` channel so we can head off any breakage
coming up ASAP.
This commit is contained in:
Alex Crichton
2020-11-06 13:23:08 -06:00
committed by GitHub
parent 8af2dbfbac
commit d2daf5064e
8 changed files with 106 additions and 87 deletions

View File

@@ -55,9 +55,11 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
# Note that we use nightly Rust here to get intra-doc links which are a
# nightly-only feature right now.
- uses: ./.github/actions/install-rust - uses: ./.github/actions/install-rust
with: with:
toolchain: nightly-2020-11-02 toolchain: nightly
- run: cargo doc --no-deps --all --exclude wasmtime-cli --exclude test-programs --exclude cranelift-codegen-meta - run: cargo doc --no-deps --all --exclude wasmtime-cli --exclude test-programs --exclude cranelift-codegen-meta
- run: cargo doc --package cranelift-codegen-meta --document-private-items - run: cargo doc --package cranelift-codegen-meta --document-private-items
- uses: actions/upload-artifact@v1 - uses: actions/upload-artifact@v1
@@ -91,8 +93,6 @@ jobs:
with: with:
submodules: true submodules: true
- uses: ./.github/actions/install-rust - uses: ./.github/actions/install-rust
with:
toolchain: nightly-2020-11-02
# Check some feature combinations of the `wasmtime` crate # Check some feature combinations of the `wasmtime` crate
- run: cargo check --manifest-path crates/wasmtime/Cargo.toml --no-default-features - run: cargo check --manifest-path crates/wasmtime/Cargo.toml --no-default-features
@@ -140,9 +140,11 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
submodules: true submodules: true
# Note that building with fuzzers requires nightly since it uses unstable
# flags to rustc.
- uses: ./.github/actions/install-rust - uses: ./.github/actions/install-rust
with: with:
toolchain: nightly-2020-11-02 toolchain: nightly
- run: cargo install cargo-fuzz --vers "^0.8" - run: cargo install cargo-fuzz --vers "^0.8"
- run: cargo fetch - run: cargo fetch
working-directory: ./fuzz working-directory: ./fuzz
@@ -199,7 +201,7 @@ jobs:
rust: beta rust: beta
- build: nightly - build: nightly
os: ubuntu-latest os: ubuntu-latest
rust: nightly-2020-11-02 rust: nightly
- build: macos - build: macos
os: macos-latest os: macos-latest
rust: stable rust: stable
@@ -268,12 +270,10 @@ jobs:
env: env:
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
# Build and test lightbeam if we're using the nightly toolchain. Note that # Build and test lightbeam. Note that
# Lightbeam tests fail right now, but we don't want to block on that. # Lightbeam tests fail right now, but we don't want to block on that.
- run: cargo build --package lightbeam - run: cargo build --package lightbeam
if: matrix.build == 'nightly'
- run: cargo test --package lightbeam - run: cargo test --package lightbeam
if: matrix.build == 'nightly'
continue-on-error: true continue-on-error: true
env: env:
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
@@ -290,7 +290,7 @@ jobs:
submodules: true submodules: true
- uses: ./.github/actions/install-rust - uses: ./.github/actions/install-rust
with: with:
toolchain: nightly-2020-11-02 toolchain: nightly
- uses: ./.github/actions/define-llvm-env - uses: ./.github/actions/define-llvm-env
# Install wasm32 targets in order to build various tests throughout the # Install wasm32 targets in order to build various tests throughout the
@@ -301,7 +301,7 @@ jobs:
# Run the x64 CI script. # Run the x64 CI script.
- run: ./ci/run-experimental-x64-ci.sh - run: ./ci/run-experimental-x64-ci.sh
env: env:
CARGO_VERSION: "+nightly-2020-11-02" CARGO_VERSION: "+nightly"
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
# Verify that cranelift's code generation is deterministic # Verify that cranelift's code generation is deterministic

38
Cargo.lock generated
View File

@@ -183,20 +183,22 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]] [[package]]
name = "capstone" name = "capstone"
version = "0.6.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "031ba51c39151a1d6336ec859646153187204b0147c7b3f6fe2de636f1b8dbb3" checksum = "f60e7f097987a09a9b678c6214b5a5eb326f9fc1e3eac88cce5d086c2b3b8dc9"
dependencies = [ dependencies = [
"capstone-sys", "capstone-sys",
"libc",
] ]
[[package]] [[package]]
name = "capstone-sys" name = "capstone-sys"
version = "0.10.0" version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fae25eddcb80e24f98c35952c37a91ff7f8d0f60dbbdafb9763e8d5cc566b8d7" checksum = "aebe07897b48983847943662bfc3198aabfa51636c81313c1955d04d857ed739"
dependencies = [ dependencies = [
"cc", "cc",
"libc",
] ]
[[package]] [[package]]
@@ -710,14 +712,14 @@ dependencies = [
[[package]] [[package]]
name = "dynasm" name = "dynasm"
version = "0.5.2" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42a814e1edeb85dd2a3c6fc0d6bf76d02ca5695d438c70ecee3d90774f3259c5" checksum = "62a59fbab09460c1569eeea9b5e4cf62f13f5198b1c2ba0e5196dd7fdd17cd42"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"byteorder", "byteorder",
"lazy_static", "lazy_static",
"owning_ref", "proc-macro-error",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn",
@@ -725,11 +727,12 @@ dependencies = [
[[package]] [[package]]
name = "dynasmrt" name = "dynasmrt"
version = "0.5.2" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a393aaeb4441a48bcf47b5b6155971f82cc1eb77e22855403ccc0415ac8328d" checksum = "85bec3edae2841d37b1c3dc7f3fd403c9061f26e9ffeeee97a3ea909b1bb2ef1"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"dynasm",
"memmap", "memmap",
] ]
@@ -1070,6 +1073,7 @@ name = "lightbeam"
version = "0.21.0" version = "0.21.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"arrayvec",
"capstone", "capstone",
"cranelift-codegen", "cranelift-codegen",
"derive_more", "derive_more",
@@ -1082,7 +1086,6 @@ dependencies = [
"more-asserts", "more-asserts",
"quickcheck", "quickcheck",
"smallvec", "smallvec",
"staticvec",
"thiserror", "thiserror",
"typemap", "typemap",
"wasmparser 0.65.0", "wasmparser 0.65.0",
@@ -1247,15 +1250,6 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "owning_ref"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce"
dependencies = [
"stable_deref_trait",
]
[[package]] [[package]]
name = "peepmatic" name = "peepmatic"
version = "0.68.0" version = "0.68.0"
@@ -1853,12 +1847,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "staticvec"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c87f4be0fd89694157f3814ca88715ad8ba6010c453b1e89ca264aee04d70b9"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.8.0" version = "0.8.0"

View File

@@ -32,7 +32,7 @@ cranelift = { path = "umbrella", version = "0.68.0" }
filecheck = "0.5.0" filecheck = "0.5.0"
log = "0.4.8" log = "0.4.8"
term = "0.6.1" term = "0.6.1"
capstone = { version = "0.6.0", optional = true } capstone = { version = "0.7.0", optional = true }
wat = { version = "1.0.18", optional = true } wat = { version = "1.0.18", optional = true }
target-lexicon = { version = "0.11", features = ["std"] } target-lexicon = { version = "0.11", features = ["std"] }
peepmatic-souper = { path = "./peepmatic/crates/souper", version = "0.68.0", optional = true } peepmatic-souper = { path = "./peepmatic/crates/souper", version = "0.68.0", optional = true }

View File

@@ -133,35 +133,40 @@ cfg_if! {
Architecture::X86_32(_) => Capstone::new() Architecture::X86_32(_) => Capstone::new()
.x86() .x86()
.mode(arch::x86::ArchMode::Mode32) .mode(arch::x86::ArchMode::Mode32)
.build()?, .build()
.map_err(map_caperr)?,
Architecture::X86_64 => Capstone::new() Architecture::X86_64 => Capstone::new()
.x86() .x86()
.mode(arch::x86::ArchMode::Mode64) .mode(arch::x86::ArchMode::Mode64)
.build()?, .build()
.map_err(map_caperr)?,
Architecture::Arm(arm) => { Architecture::Arm(arm) => {
if arm.is_thumb() { if arm.is_thumb() {
Capstone::new() Capstone::new()
.arm() .arm()
.mode(arch::arm::ArchMode::Thumb) .mode(arch::arm::ArchMode::Thumb)
.build()? .build()
.map_err(map_caperr)?
} else { } else {
Capstone::new() Capstone::new()
.arm() .arm()
.mode(arch::arm::ArchMode::Arm) .mode(arch::arm::ArchMode::Arm)
.build()? .build()
.map_err(map_caperr)?
} }
} }
Architecture::Aarch64 {..} => { Architecture::Aarch64 {..} => {
let mut cs = Capstone::new() let mut cs = Capstone::new()
.arm64() .arm64()
.mode(arch::arm64::ArchMode::Arm) .mode(arch::arm64::ArchMode::Arm)
.build()?; .build()
.map_err(map_caperr)?;
// AArch64 uses inline constants rather than a separate constant pool right now. // AArch64 uses inline constants rather than a separate constant pool right now.
// Without this option, Capstone will stop disassembling as soon as it sees // Without this option, Capstone will stop disassembling as soon as it sees
// an inline constant that is not also a valid instruction. With this option, // an inline constant that is not also a valid instruction. With this option,
// Capstone will print a `.byte` directive with the bytes of the inline constant // Capstone will print a `.byte` directive with the bytes of the inline constant
// and continue to the next instruction. // and continue to the next instruction.
cs.set_skipdata(true)?; cs.set_skipdata(true).map_err(map_caperr)?;
cs cs
} }
_ => anyhow::bail!("Unknown ISA"), _ => anyhow::bail!("Unknown ISA"),
@@ -208,6 +213,10 @@ cfg_if! {
} }
Ok(()) Ok(())
} }
fn map_caperr(err: capstone::Error) -> anyhow::Error{
anyhow::format_err!("{}", err)
}
} else { } else {
pub fn print_disassembly(_: &dyn TargetIsa, _: &[u8]) -> Result<()> { pub fn print_disassembly(_: &dyn TargetIsa, _: &[u8]) -> Result<()> {
println!("\nNo disassembly available."); println!("\nNo disassembly available.");

View File

@@ -11,17 +11,17 @@ keywords = ["webassembly", "wasm", "compile", "compiler", "jit"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
capstone = "0.6.0" arrayvec = "0.5"
capstone = "0.7.0"
cranelift-codegen = { path = "../../cranelift/codegen", version = "0.68.0" } cranelift-codegen = { path = "../../cranelift/codegen", version = "0.68.0" }
derive_more = "0.99" derive_more = "0.99"
dynasm = "0.5.2" dynasm = "1.0.0"
dynasmrt = "0.5.2" dynasmrt = "1.0.0"
iter-enum = "0.2" iter-enum = "0.2"
itertools = "0.9.0" itertools = "0.9.0"
memoffset = "0.6.0" memoffset = "0.6.0"
more-asserts = "0.2.1" more-asserts = "0.2.1"
smallvec = "1.0.0" smallvec = "1.0.0"
staticvec = "0.10"
thiserror = "1.0.9" thiserror = "1.0.9"
typemap = "0.3" typemap = "0.3"
wasmparser = "0.65.0" wasmparser = "0.65.0"

View File

@@ -2,6 +2,7 @@ use capstone::prelude::*;
use dynasmrt::AssemblyOffset; use dynasmrt::AssemblyOffset;
use std::error::Error; use std::error::Error;
use std::fmt::{Display, Write}; use std::fmt::{Display, Write};
use std::io;
pub fn disassemble<D: Display>( pub fn disassemble<D: Display>(
mem: &[u8], mem: &[u8],
@@ -10,10 +11,11 @@ pub fn disassemble<D: Display>(
let cs = Capstone::new() let cs = Capstone::new()
.x86() .x86()
.mode(arch::x86::ArchMode::Mode64) .mode(arch::x86::ArchMode::Mode64)
.build()?; .build()
.map_err(map_caperr)?;
println!("{} bytes:", mem.len()); println!("{} bytes:", mem.len());
let insns = cs.disasm_all(&mem, 0x0)?; let insns = cs.disasm_all(&mem, 0x0).map_err(map_caperr)?;
for i in insns.iter() { for i in insns.iter() {
let mut line = String::new(); let mut line = String::new();
@@ -49,3 +51,7 @@ pub fn disassemble<D: Display>(
Ok(()) Ok(())
} }
fn map_caperr(err: capstone::Error) -> Box<dyn Error> {
Box::new(io::Error::new(io::ErrorKind::Other, err.to_string()))
}

View File

@@ -1,5 +1,4 @@
#![cfg_attr(test, feature(test))] #![cfg_attr(test, feature(test))]
#![feature(proc_macro_hygiene)]
#[cfg(test)] #[cfg(test)]
extern crate test; extern crate test;

View File

@@ -1569,9 +1569,17 @@ where
fn next( fn next(
&mut self, &mut self,
) -> Result<Option<impl ExactSizeIterator<Item = OperatorFromWasm> + '_>, Error> { ) -> Result<Option<impl ExactSizeIterator<Item = OperatorFromWasm> + '_>, Error> {
use arrayvec::ArrayVec;
use derive_more::From; use derive_more::From;
use iter_enum::{ExactSizeIterator, Iterator}; use iter_enum::{ExactSizeIterator, Iterator};
use staticvec::{staticvec, StaticVec, StaticVecIntoIter};
macro_rules! vec {
($($a:expr),* $(,)?) => {{
let mut a = ArrayVec::new();
$(a.push($a);)*
vec(a)
}};
}
struct Consts { struct Consts {
inner: <Vec<Value> as IntoIterator>::IntoIter, inner: <Vec<Value> as IntoIterator>::IntoIter,
@@ -1601,13 +1609,13 @@ where
Output::Consts(impl_trait_hack(consts)) Output::Consts(impl_trait_hack(consts))
} }
fn vec(vals: impl Into<StaticVec<OperatorFromWasm, 5>>) -> Output { fn vec(vals: ArrayVec<[OperatorFromWasm; 5]>) -> Output {
vals.into().into_iter().into() vals.into_iter().into()
} }
fn iter(vals: impl IntoIterator<Item = OperatorFromWasm>) -> Output { fn iter(vals: impl IntoIterator<Item = OperatorFromWasm>) -> Output {
let mut vals = vals.into_iter(); let mut vals = vals.into_iter();
let v = StaticVec::from_iter(vals.by_ref()); let v = ArrayVec::from_iter(vals.by_ref());
if let Some(next) = vals.next() { if let Some(next) = vals.next() {
let mut v = Vec::from_iter(v); let mut v = Vec::from_iter(v);
v.push(next); v.push(next);
@@ -1629,7 +1637,7 @@ where
#[derive(From, Iterator, ExactSizeIterator)] #[derive(From, Iterator, ExactSizeIterator)]
enum Output { enum Output {
Consts(Consts), Consts(Consts),
FixedLength(StaticVecIntoIter<OperatorFromWasm, 5>), FixedLength(arrayvec::IntoIter<[OperatorFromWasm; 5]>),
VariableLength(std::vec::IntoIter<OperatorFromWasm>), VariableLength(std::vec::IntoIter<OperatorFromWasm>),
None(std::iter::Empty<OperatorFromWasm>), None(std::iter::Empty<OperatorFromWasm>),
One(std::iter::Once<OperatorFromWasm>), One(std::iter::Once<OperatorFromWasm>),
@@ -1718,13 +1726,13 @@ where
has_else: false, .. has_else: false, ..
} = block.kind } = block.kind
{ {
break vec([ break vec![
Operator::Label((block.id, NameTag::Else)), Operator::Label((block.id, NameTag::Else)),
Operator::Br { Operator::Br {
target: BrTarget::Label(end_label), target: BrTarget::Label(end_label),
}, },
Operator::Label(end_label), Operator::Label(end_label),
]); ];
} else { } else {
break one(Operator::Label((block.id, NameTag::End))); break one(Operator::Label((block.id, NameTag::End)));
} }
@@ -1788,14 +1796,14 @@ where
let block_param_type_wasm = self.block_params_with_wasm_type(ty)?; let block_param_type_wasm = self.block_params_with_wasm_type(ty)?;
let label = (id, NameTag::Header); let label = (id, NameTag::Header);
vec([ vec![
Operator::loop_(self.block_params(), label), Operator::loop_(self.block_params(), label),
Operator::end(block_param_type_wasm.collect(), (id, NameTag::End)), Operator::end(block_param_type_wasm.collect(), (id, NameTag::End)),
Operator::Br { Operator::Br {
target: BrTarget::Label(label), target: BrTarget::Label(label),
}, },
Operator::Label(label), Operator::Label(label),
]) ]
} }
WasmOperator::If { ty } => { WasmOperator::If { ty } => {
let id = self.next_id(); let id = self.next_id();
@@ -1814,7 +1822,7 @@ where
(id, NameTag::Else), (id, NameTag::Else),
(id, NameTag::End), (id, NameTag::End),
); );
vec([ vec![
Operator::block(self.block_params(), then), Operator::block(self.block_params(), then),
Operator::block(self.block_params(), else_), Operator::block(self.block_params(), else_),
Operator::end(block_param_type_wasm.collect(), end), Operator::end(block_param_type_wasm.collect(), end),
@@ -1823,7 +1831,7 @@ where
else_: BrTarget::Label(else_).into(), else_: BrTarget::Label(else_).into(),
}, },
Operator::Label(then), Operator::Label(then),
]) ]
} }
WasmOperator::Else => { WasmOperator::Else => {
let block = self let block = self
@@ -1844,12 +1852,15 @@ where
let label = (block.id, NameTag::Else); let label = (block.id, NameTag::Else);
iter(to_drop.into_iter().map(Operator::Drop).chain(staticvec![ iter(
Operator::Br { to_drop
.into_iter()
.map(Operator::Drop)
.chain(Some(Operator::Br {
target: BrTarget::Label((block.id, NameTag::End)), target: BrTarget::Label((block.id, NameTag::End)),
}, }))
Operator::Label(label) .chain(Some(Operator::Label(label))),
])) )
} }
WasmOperator::End => { WasmOperator::End => {
let block = self let block = self
@@ -1869,16 +1880,19 @@ where
let else_ = (block.id, NameTag::Else); let else_ = (block.id, NameTag::Else);
let end = (block.id, NameTag::End); let end = (block.id, NameTag::End);
iter(to_drop.map(Operator::Drop).into_iter().chain(staticvec![ iter(
Operator::Br { to_drop
.map(Operator::Drop)
.into_iter()
.chain(Some(Operator::Br {
target: BrTarget::Label(end), target: BrTarget::Label(end),
}, }))
Operator::Label(else_), .chain(Some(Operator::Label(else_)))
Operator::Br { .chain(Some(Operator::Br {
target: BrTarget::Label(end), target: BrTarget::Label(end),
}, }))
Operator::Label(end), .chain(Some(Operator::Label(end))),
])) )
} else { } else {
if self.control_frames.is_empty() { if self.control_frames.is_empty() {
self.is_done = true; self.is_done = true;
@@ -1889,12 +1903,15 @@ where
} else if block.needs_end_label() { } else if block.needs_end_label() {
let label = (block.id, NameTag::End); let label = (block.id, NameTag::End);
iter(to_drop.map(Operator::Drop).into_iter().chain(staticvec![ iter(
Operator::Br { to_drop
.map(Operator::Drop)
.into_iter()
.chain(Some(Operator::Br {
target: BrTarget::Label(label), target: BrTarget::Label(label),
}, }))
Operator::Label(label) .chain(Some(Operator::Label(label))),
])) )
} else { } else {
iter(to_drop.map(Operator::Drop).into_iter()) iter(to_drop.map(Operator::Drop).into_iter())
} }
@@ -1923,7 +1940,7 @@ where
let block = &mut self.control_frames[relative_depth as _]; let block = &mut self.control_frames[relative_depth as _];
block.mark_branched_to(); block.mark_branched_to();
vec([ vec![
Operator::block(params, label), Operator::block(params, label),
Operator::BrIf { Operator::BrIf {
then: BrTargetDrop { then: BrTargetDrop {
@@ -1933,7 +1950,7 @@ where
else_: BrTarget::Label(label).into(), else_: BrTarget::Label(label).into(),
}, },
Operator::Label(label), Operator::Label(label),
]) ]
} }
WasmOperator::BrTable { table } => { WasmOperator::BrTable { table } => {
self.unreachable = true; self.unreachable = true;
@@ -2007,7 +2024,7 @@ where
let depth = depth let depth = depth
.try_into() .try_into()
.map_err(|_| Error::Microwasm("LocalSet - Local out of range".into()))?; .map_err(|_| Error::Microwasm("LocalSet - Local out of range".into()))?;
vec([Operator::Swap(depth), Operator::Drop(0..=0)]) vec![Operator::Swap(depth), Operator::Drop(0..=0)]
} }
WasmOperator::LocalTee { local_index } => { WasmOperator::LocalTee { local_index } => {
let depth = self let depth = self
@@ -2017,11 +2034,11 @@ where
let depth = depth let depth = depth
.try_into() .try_into()
.map_err(|_| Error::Microwasm("LocalTee - Local out of range".into()))?; .map_err(|_| Error::Microwasm("LocalTee - Local out of range".into()))?;
vec([ vec![
Operator::Pick(0), Operator::Pick(0),
Operator::Swap(depth), Operator::Swap(depth),
Operator::Drop(0..=0), Operator::Drop(0..=0),
]) ]
} }
WasmOperator::GlobalGet { global_index } => one(Operator::GlobalGet(global_index)), WasmOperator::GlobalGet { global_index } => one(Operator::GlobalGet(global_index)),
WasmOperator::GlobalSet { global_index } => one(Operator::GlobalSet(global_index)), WasmOperator::GlobalSet { global_index } => one(Operator::GlobalSet(global_index)),