diff --git a/mm0-rs/Cargo.lock b/mm0-rs/Cargo.lock index d55b1417..e459d6a0 100644 --- a/mm0-rs/Cargo.lock +++ b/mm0-rs/Cargo.lock @@ -126,18 +126,18 @@ checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" [[package]] name = "bit-set" -version = "0.6.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitflags" @@ -522,21 +522,21 @@ dependencies = [ ] [[package]] -name = "fxhash" -version = "0.2.1" +name = "getopts" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ - "byteorder", + "unicode-width", ] [[package]] -name = "getopts" -version = "0.2.21" +name = "hashbrown" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" dependencies = [ - "unicode-width", + "ahash", ] [[package]] @@ -890,7 +890,7 @@ dependencies = [ "bitflags 2.6.0", "bumpalo", "byteorder", - "hashbrown", + "hashbrown 0.14.5", "hex", "if_chain", "im", @@ -1170,16 +1170,23 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.2.3" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a8d23b35d7177df3b9d31ed8a9ab4bf625c668be77a319d4f5efd4a5257701c" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" dependencies = [ - "fxhash", + "hashbrown 0.13.2", "log", + "rustc-hash", "slice-group-by", "smallvec", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.2.3" diff --git a/mm0-rs/Cargo.toml b/mm0-rs/Cargo.toml index d1883bc6..b8f0e077 100644 --- a/mm0-rs/Cargo.toml +++ b/mm0-rs/Cargo.toml @@ -50,7 +50,7 @@ annotate-snippets = "0.11" libc = "0.2" zerocopy = "0.7" memchr = "2.7" -bit-set = "0.6" +bit-set = "0.8" typed-arena = "2.0" mm0_deepsize_derive = { path = "components/mm0_deepsize_derive", optional = true } debug_derive = { path = "components/debug_derive" } diff --git a/mm0-rs/components/mm0_deepsize/Cargo.toml b/mm0-rs/components/mm0_deepsize/Cargo.toml index 083ab906..9bfc6409 100644 --- a/mm0-rs/components/mm0_deepsize/Cargo.toml +++ b/mm0-rs/components/mm0_deepsize/Cargo.toml @@ -18,8 +18,8 @@ mm0_deepsize_derive = { version = "0.1.1", path = "../mm0_deepsize_derive" } num = { version = "0.4", optional = true } typed-arena = { version = "2.0", optional = true } smallvec = { version = "1.8", optional = true } -bit-vec = { version = "0.7", optional = true } -bit-set = { version = "0.6", optional = true } +bit-vec = { version = "0.8", optional = true } +bit-set = { version = "0.8", optional = true } lsp-types = { version = "0.97", optional = true } futures = { version = "0.3", optional = true } hybrid-rc = { version = "0.6", optional = true } diff --git a/mm0-rs/components/mmcc/Cargo.toml b/mm0-rs/components/mmcc/Cargo.toml index 924ded9d..8519cce9 100644 --- a/mm0-rs/components/mmcc/Cargo.toml +++ b/mm0-rs/components/mmcc/Cargo.toml @@ -23,13 +23,13 @@ if_chain = "1.0" smallvec = { version = "1.8", features = ["union"] } arrayvec = "0.7" im = "15.1" -bit-vec = "0.7" -bit-set = "0.6" +bit-vec = "0.8" +bit-set = "0.8" hashbrown = "0.14" typed-arena = "2.0" # simplelog = "0.11" bumpalo = { version = "3.10", features = ["boxed", "collections"] } -regalloc2 = "0.2" +regalloc2 = "0.9" mm0_util = { path = "../mm0_util", default-features = false } mm0_deepsize = { path = "../mm0_deepsize", optional = true, features = [ "num", "typed-arena", "smallvec", "bit-vec", "bit-set"] } diff --git a/mm0-rs/components/mmcc/src/arch/x86/mod.rs b/mm0-rs/components/mmcc/src/arch/x86/mod.rs index a875e61e..26dd4cdd 100644 --- a/mm0-rs/components/mmcc/src/arch/x86/mod.rs +++ b/mm0-rs/components/mmcc/src/arch/x86/mod.rs @@ -85,17 +85,51 @@ pub(crate) fn caller_saved() -> impl DoubleEndedIterator + Clone { } pub(crate) static MACHINE_ENV: Lazy = Lazy::new(|| MachineEnv { - preferred_regs_by_class: [CALLER_SAVED.map(|r| r.0).into(), vec![]], - non_preferred_regs_by_class: [CALLEE_SAVED.map(|r| r.0).into(), vec![]], + preferred_regs_by_class: [CALLER_SAVED.map(|r| r.0).into(), vec![], vec![]], + non_preferred_regs_by_class: [CALLEE_SAVED.map(|r| r.0).into(), vec![], vec![]], + scratch_by_class: [None; 3], fixed_stack_slots: vec![], }); -#[derive(Copy, Clone, Default)] -pub(crate) struct PRegSet(u16); +/// A set of physical registers. For x86, this can be stored as a 16 bit bitfield. +#[derive(Copy, Clone, Default, Debug)] +pub struct PRegSet(u16); impl PRegSet { #[inline] pub(crate) fn insert(&mut self, r: PReg) { self.0 |= 1 << r.index() } #[inline] pub(crate) fn get(self, r: PReg) -> bool { self.0 & (1 << r.index()) != 0 } #[inline] pub(crate) fn remove(&mut self, r: PReg) { self.0 &= !(1 << r.index()) } + + /// An iterator over the registers in the set. + pub fn iter(self) -> impl Iterator { + (0..16).map(PReg::new).filter(move |&r| self.get(r)) + } +} + +impl std::ops::BitOrAssign for PRegSet { + fn bitor_assign(&mut self, rhs: Self) { + self.0 |= rhs.0 + } +} + +impl From for regalloc2::PRegSet { + fn from(val: PRegSet) -> Self { + let mut out = Self::empty(); + for i in 0..16 { + let r = PReg::new(i); + if val.get(r) { + out.add(r.0) + } + } + out + } +} + +impl FromIterator for PRegSet { + fn from_iter>(iter: T) -> Self { + let mut out = Self::default(); + for i in iter { out.insert(i); } + out + } } /// These indicate the form of a scalar shift/rotate: left, signed right, unsigned right. @@ -937,7 +971,7 @@ pub(crate) enum Inst { f: ProcId, operands: Box<[Operand]>, /// If `clobbers = None` then this call does not return. - clobbers: Option>, + clobbers: Option, }, // /// Indirect call: `callq r/m`. // CallUnknown { @@ -981,7 +1015,6 @@ impl Debug for Inst { let vreg = VReg(self.0.vreg()); match self.0.kind() { OperandKind::Def => write!(f, "out ")?, - OperandKind::Mod => write!(f, "inout ")?, OperandKind::Use => {} } match self.0.constraint() { @@ -1146,11 +1179,11 @@ impl VInst for Inst { } } - fn clobbers(&self) -> &[PReg] { + fn clobbers(&self) -> PRegSet { match self { - Inst::CallKnown { clobbers: Some(cl), .. } => cl, - Inst::SysCall { f, .. } if f.returns() => &[RCX, R11], - _ => &[], + &Inst::CallKnown { clobbers: Some(cl), .. } => cl, + Inst::SysCall { f, .. } if f.returns() => [RCX, R11].into_iter().collect(), + _ => Default::default(), } } } diff --git a/mm0-rs/components/mmcc/src/build_vcode.rs b/mm0-rs/components/mmcc/src/build_vcode.rs index af84829e..fcd2c7d1 100644 --- a/mm0-rs/components/mmcc/src/build_vcode.rs +++ b/mm0-rs/components/mmcc/src/build_vcode.rs @@ -787,7 +787,7 @@ impl<'a> LowerCtx<'a> { self.emit(Inst::CallKnown { f, operands: operands.into(), - clobbers: Some(fabi.clobbers.clone()), + clobbers: Some(fabi.clobbers), }); let mut ret_regs = ret_regs.into_iter(); for (arg, &(vr, v)) in fabi.rets.iter().zip(rets) { diff --git a/mm0-rs/components/mmcc/src/regalloc.rs b/mm0-rs/components/mmcc/src/regalloc.rs index 3e240750..adf23ee6 100644 --- a/mm0-rs/components/mmcc/src/regalloc.rs +++ b/mm0-rs/components/mmcc/src/regalloc.rs @@ -23,7 +23,7 @@ use crate::types::vcode::{self, IsReg, InstId, ProcAbi, SpillId, BlockId, ChunkV impl vcode::VCode { fn do_regalloc(&self) -> regalloc2::Output { - let opts = regalloc2::RegallocOptions { verbose_log: true }; + let opts = regalloc2::RegallocOptions { verbose_log: true, validate_ssa: true }; regalloc2::run(self, &MACHINE_ENV, &opts).expect("fatal regalloc error") } } @@ -283,7 +283,8 @@ fn get_clobbers(vcode: &VCode, out: ®alloc2::Output) -> PRegSet { if let Some(r) = to.as_reg() { result.insert(PReg(r)) } } for (i, _) in vcode.insts.enum_iter() { - for &r in vcode.inst_clobbers(i) { result.insert(PReg(r)) } + use crate::types::vcode::Inst; + result |= vcode.insts[i].clobbers(); for (op, alloc) in vcode.inst_operands(i).iter().zip(out.inst_allocs(i)) { if op.kind() != regalloc2::OperandKind::Use { if let Some(r) = alloc.as_reg() { result.insert(PReg(r)) } diff --git a/mm0-rs/components/mmcc/src/types/vcode.rs b/mm0-rs/components/mmcc/src/types/vcode.rs index 2ea30cd5..b22b67f9 100644 --- a/mm0-rs/components/mmcc/src/types/vcode.rs +++ b/mm0-rs/components/mmcc/src/types/vcode.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, fmt::{Debug, Display}, iter::FromIterator}; -use crate::{Idx, types::{IdxVec, mir}, arch::PReg}; +use crate::{arch::{PReg, PRegSet}, types::{mir, IdxVec}, Idx}; use mm0_util::u32_as_usize; pub(crate) use regalloc2::{RegClass, InstRange, Operand, Inst as InstId}; @@ -112,7 +112,7 @@ pub trait Inst: Sized { fn collect_operands(&self, _: &mut Vec); /// Get the clobbers for an instruction. - fn clobbers(&self) -> &[PReg]; + fn clobbers(&self) -> PRegSet; } /// Conceptually the same as `IdxVec>`, but shares allocations between the vectors. @@ -249,7 +249,7 @@ pub struct ProcAbi { /// The total size of the stack-allocated incoming arguments in bytes pub args_space: u32, /// The registers that are clobbered by the call. - pub clobbers: Box<[PReg]>, + pub clobbers: PRegSet, } /// A low level representation of a function, after instruction selection but before @@ -375,13 +375,10 @@ impl regalloc2::Function for VCode { self.insts[insn].branch_blockparams(succ_idx) } - fn is_move(&self, insn: InstId) -> Option<(Operand, Operand)> { self.insts[insn].is_move() } + // fn is_move(&self, insn: InstId) -> Option<(Operand, Operand)> { self.insts[insn].is_move() } fn inst_operands(&self, insn: InstId) -> &[Operand] { &self.operands[insn] } - fn inst_clobbers(&self, insn: InstId) -> &[regalloc2::PReg] { - let ret = self.insts[insn].clobbers(); - #[allow(clippy::transmute_ptr_to_ptr)] - // Safety: `PReg` is repr(transparent) - unsafe { std::mem::transmute::<&[PReg], &[regalloc2::PReg]>(ret) } + fn inst_clobbers(&self, insn: InstId) -> regalloc2::PRegSet { + self.insts[insn].clobbers().into() } fn num_vregs(&self) -> usize { self.num_vregs } fn spillslot_size(&self, _: regalloc2::RegClass) -> usize { 1 } diff --git a/mm0-rs/src/mmc/proof/compiler.rs b/mm0-rs/src/mmc/proof/compiler.rs index 3ab8aef6..8c4ad431 100644 --- a/mm0-rs/src/mmc/proof/compiler.rs +++ b/mm0-rs/src/mmc/proof/compiler.rs @@ -1225,7 +1225,7 @@ impl<'a> ProcProver<'a> { let (vctx1, sz1) = (vctx.e, *vctx.nvars); let mctx1 = mctx.1; let args2 = app!(self.thm, (mkArgs args mctx1)); - let (clob, h3) = self.accum_clob(&mut mctx, abi.clobbers.iter().map(|r| r.index())); + let (clob, h3) = self.accum_clob(&mut mctx, abi.clobbers.iter().map(PReg::index)); let mctx2 = mctx.1; let h4 = self.ok_prologue(&mut mctx, prol); let mctx3 = mctx.1;