Add support for reftypes/stackmaps and Stack constraints, and misc API changes.
The main enhancement in this commit is support for reference types and stackmaps. This requires tracking whether each VReg is a "reference" or "pointer". At certain instructions designated as "safepoints", the regalloc will (i) ensure that all references are in spillslots rather than in registers, and (ii) provide a list of exactly which spillslots have live references at that program point. This can be used by, e.g., a GC to trace and possibly modify pointers. The stackmap of spillslots is precise: it includes all live references, and *only* live references. This commit also brings in some API tweaks as part of the in-progress Cranelift glue. In particular, it makes Allocations and Operands mutually disjoint by using the same bitfield for the type-tag in both and choosing non-overlapping tags. This will allow instructions to carry an Operand for each register slot and then overwrite these in place with Allocations. The `OperandOrAllocation` type does the necessary magic to make this look like an enum, but staying in 32 bits.
This commit is contained in:
@@ -48,6 +48,18 @@ impl BitVec {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assign(&mut self, other: &Self) {
|
||||
if other.bits.len() > 0 {
|
||||
self.ensure_idx(other.bits.len() - 1);
|
||||
}
|
||||
for i in 0..other.bits.len() {
|
||||
self.bits[i] = other.bits[i];
|
||||
}
|
||||
for i in other.bits.len()..self.bits.len() {
|
||||
self.bits[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get(&mut self, idx: usize) -> bool {
|
||||
let word = idx / BITS_PER_WORD;
|
||||
@@ -59,16 +71,21 @@ impl BitVec {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn or(&mut self, other: &Self) {
|
||||
pub fn or(&mut self, other: &Self) -> bool {
|
||||
if other.bits.is_empty() {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
let last_idx = other.bits.len() - 1;
|
||||
self.ensure_idx(last_idx);
|
||||
|
||||
let mut changed = false;
|
||||
for (self_word, other_word) in self.bits.iter_mut().zip(other.bits.iter()) {
|
||||
if *other_word & !*self_word != 0 {
|
||||
changed = true;
|
||||
}
|
||||
*self_word |= *other_word;
|
||||
}
|
||||
changed
|
||||
}
|
||||
|
||||
pub fn and(&mut self, other: &Self) {
|
||||
@@ -91,6 +108,29 @@ impl BitVec {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::cmp::PartialEq for BitVec {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let limit = std::cmp::min(self.bits.len(), other.bits.len());
|
||||
for i in 0..limit {
|
||||
if self.bits[i] != other.bits[i] {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for i in limit..self.bits.len() {
|
||||
if self.bits[i] != 0 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for i in limit..other.bits.len() {
|
||||
if other.bits[i] != 0 {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
impl std::cmp::Eq for BitVec {}
|
||||
|
||||
pub struct SetBitsIter<'a> {
|
||||
words: &'a [u64],
|
||||
word_idx: usize,
|
||||
|
||||
Reference in New Issue
Block a user