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:
Chris Fallin
2021-04-17 21:28:26 -07:00
parent 33ac6cb41d
commit a08b0121a0
6 changed files with 686 additions and 91 deletions

View File

@@ -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,