Chaos mode MVP: Skip branch optimization in MachBuffer (#6039)

* fuzz: Add chaos mode control plane

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* fuzz: Skip branch optimization with chaos mode

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* fuzz: Rename chaos engine -> control plane

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* chaos mode: refactoring ControlPlane to be passed through the call stack by reference

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Remo Senekowitsch <contact@remsle.dev>

* fuzz: annotate chaos todos

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* fuzz: cleanup control plane

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* fuzz: remove control plane from compiler context

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* fuzz: move control plane into emit state

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* fuzz: fix remaining compiler errors

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* fix tests

* refactor emission state ctrl plane accessors

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* centralize conditional compilation of chaos mode

Also cleanup a few straggling dependencies on cranelift-control
that aren't needed anymore.

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* add cranelift-control to published crates

prtest:full

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

* add cranelift-control to public crates

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>

---------

Co-authored-by: Falk Zwimpfer <24669719+FalkZ@users.noreply.github.com>
Co-authored-by: Moritz Waser <mzrw.dev@pm.me>
Co-authored-by: Remo Senekowitsch <contact@remsle.dev>
This commit is contained in:
Remo Senekowitsch
2023-04-05 21:28:46 +02:00
committed by GitHub
parent 064968b01d
commit 7eb8914090
61 changed files with 815 additions and 245 deletions

View File

@@ -148,6 +148,7 @@ use crate::machinst::{
};
use crate::timing;
use crate::trace;
use cranelift_control::ControlPlane;
use cranelift_entity::{entity_impl, SecondaryMap};
use smallvec::SmallVec;
use std::convert::TryFrom;
@@ -523,7 +524,7 @@ impl<I: VCodeInst> MachBuffer<I> {
}
/// Bind a label to the current offset. A label can only be bound once.
pub fn bind_label(&mut self, label: MachLabel) {
pub fn bind_label(&mut self, label: MachLabel, ctrl_plane: &mut ControlPlane) {
trace!(
"MachBuffer: bind label {:?} at offset {}",
label,
@@ -542,7 +543,7 @@ impl<I: VCodeInst> MachBuffer<I> {
// offset and added it to the list (which contains all labels at the
// current offset).
self.optimize_branches();
self.optimize_branches(ctrl_plane);
// Post-invariant: by `optimize_branches()` (see argument there).
}
@@ -773,7 +774,11 @@ impl<I: VCodeInst> MachBuffer<I> {
// fixup record referring to that last branch is removed.
}
fn optimize_branches(&mut self) {
fn optimize_branches(&mut self, ctrl_plane: &mut ControlPlane) {
if ctrl_plane.get_decision() {
return;
}
self.lazily_clear_labels_at_tail();
// Invariants valid at this point.
@@ -1141,13 +1146,18 @@ impl<I: VCodeInst> MachBuffer<I> {
/// Should only be called if `island_needed()` returns true, i.e., if we
/// actually reach a deadline. It's not necessarily a problem to do so
/// otherwise but it may result in unnecessary work during emission.
pub fn emit_island(&mut self, distance: CodeOffset) {
self.emit_island_maybe_forced(false, distance);
pub fn emit_island(&mut self, distance: CodeOffset, ctrl_plane: &mut ControlPlane) {
self.emit_island_maybe_forced(false, distance, ctrl_plane);
}
/// Same as `emit_island`, but an internal API with a `force_veneers`
/// argument to force all veneers to always get emitted for debugging.
fn emit_island_maybe_forced(&mut self, force_veneers: bool, distance: CodeOffset) {
fn emit_island_maybe_forced(
&mut self,
force_veneers: bool,
distance: CodeOffset,
ctrl_plane: &mut ControlPlane,
) {
// We're going to purge fixups, so no latest-branch editing can happen
// anymore.
self.latest_branches.clear();
@@ -1190,7 +1200,7 @@ impl<I: VCodeInst> MachBuffer<I> {
self.start_srcloc(loc);
}
self.align_to(I::LabelUse::ALIGN);
self.bind_label(label);
self.bind_label(label, ctrl_plane);
self.add_trap(code);
if let Some(map) = stack_map {
let extent = StackMapExtent::UpcomingBytes(I::TRAP_OPCODE.len() as u32);
@@ -1204,7 +1214,7 @@ impl<I: VCodeInst> MachBuffer<I> {
for MachLabelConstant { label, align, data } in mem::take(&mut self.pending_constants) {
self.align_to(align);
self.bind_label(label);
self.bind_label(label, ctrl_plane);
self.put_data(&data[..]);
}
@@ -1328,7 +1338,11 @@ impl<I: VCodeInst> MachBuffer<I> {
self.use_label_at_offset(veneer_fixup_off, label, veneer_label_use);
}
fn finish_emission_maybe_forcing_veneers(&mut self, force_veneers: bool) {
fn finish_emission_maybe_forcing_veneers(
&mut self,
force_veneers: bool,
ctrl_plane: &mut ControlPlane,
) {
while !self.pending_constants.is_empty()
|| !self.pending_traps.is_empty()
|| !self.fixup_records.is_empty()
@@ -1336,7 +1350,7 @@ impl<I: VCodeInst> MachBuffer<I> {
// `emit_island()` will emit any pending veneers and constants, and
// as a side-effect, will also take care of any fixups with resolved
// labels eagerly.
self.emit_island_maybe_forced(force_veneers, u32::MAX);
self.emit_island_maybe_forced(force_veneers, u32::MAX, ctrl_plane);
}
// Ensure that all labels have been fixed up after the last island is emitted. This is a
@@ -1346,14 +1360,14 @@ impl<I: VCodeInst> MachBuffer<I> {
}
/// Finish any deferred emissions and/or fixups.
pub fn finish(mut self) -> MachBufferFinalized<Stencil> {
pub fn finish(mut self, ctrl_plane: &mut ControlPlane) -> MachBufferFinalized<Stencil> {
let _tt = timing::vcode_emit_finish();
// Do any optimizations on branches at tail of buffer, as if we
// had bound one last label.
self.optimize_branches();
self.optimize_branches(ctrl_plane);
self.finish_emission_maybe_forcing_veneers(false);
self.finish_emission_maybe_forcing_veneers(false, ctrl_plane);
let mut srclocs = self.srclocs;
srclocs.sort_by_key(|entry| entry.start);
@@ -1713,19 +1727,28 @@ impl<I: VCodeInst> MachTextSectionBuilder<I> {
}
impl<I: VCodeInst> TextSectionBuilder for MachTextSectionBuilder<I> {
fn append(&mut self, labeled: bool, func: &[u8], align: u32) -> u64 {
fn append(
&mut self,
labeled: bool,
func: &[u8],
align: u32,
ctrl_plane: &mut ControlPlane,
) -> u64 {
// Conditionally emit an island if it's necessary to resolve jumps
// between functions which are too far away.
let size = func.len() as u32;
if self.force_veneers || self.buf.island_needed(size) {
self.buf.emit_island_maybe_forced(self.force_veneers, size);
self.buf
.emit_island_maybe_forced(self.force_veneers, size, ctrl_plane);
}
self.buf.align_to(align);
let pos = self.buf.cur_offset();
if labeled {
self.buf
.bind_label(MachLabel::from_block(BlockIndex::new(self.next_func)));
self.buf.bind_label(
MachLabel::from_block(BlockIndex::new(self.next_func)),
ctrl_plane,
);
self.next_func += 1;
}
self.buf.put_data(func);
@@ -1748,13 +1771,13 @@ impl<I: VCodeInst> TextSectionBuilder for MachTextSectionBuilder<I> {
self.force_veneers = true;
}
fn finish(&mut self) -> Vec<u8> {
fn finish(&mut self, ctrl_plane: &mut ControlPlane) -> Vec<u8> {
// Double-check all functions were pushed.
assert_eq!(self.next_func, self.buf.label_offsets.len());
// Finish up any veneers, if necessary.
self.buf
.finish_emission_maybe_forcing_veneers(self.force_veneers);
.finish_emission_maybe_forcing_veneers(self.force_veneers, ctrl_plane);
// We don't need the data any more, so return it to the caller.
mem::take(&mut self.buf.data).into_vec()
@@ -1770,7 +1793,7 @@ mod test {
use crate::ir::UserExternalNameRef;
use crate::isa::aarch64::inst::xreg;
use crate::isa::aarch64::inst::{BranchTarget, CondBrKind, EmitInfo, Inst};
use crate::machinst::MachInstEmit;
use crate::machinst::{MachInstEmit, MachInstEmitState};
use crate::settings;
use std::default::Default;
use std::vec::Vec;
@@ -1786,14 +1809,14 @@ mod test {
fn test_elide_jump_to_next() {
let info = EmitInfo::new(settings::Flags::new(settings::builder()));
let mut buf = MachBuffer::new();
let mut state = Default::default();
let mut state = <Inst as MachInstEmit>::State::default();
buf.reserve_labels_for_blocks(2);
buf.bind_label(label(0));
buf.bind_label(label(0), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(1) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(1));
let buf = buf.finish();
buf.bind_label(label(1), state.ctrl_plane_mut());
let buf = buf.finish(state.ctrl_plane_mut());
assert_eq!(0, buf.total_size());
}
@@ -1801,11 +1824,11 @@ mod test {
fn test_elide_trivial_jump_blocks() {
let info = EmitInfo::new(settings::Flags::new(settings::builder()));
let mut buf = MachBuffer::new();
let mut state = Default::default();
let mut state = <Inst as MachInstEmit>::State::default();
buf.reserve_labels_for_blocks(4);
buf.bind_label(label(0));
buf.bind_label(label(0), state.ctrl_plane_mut());
let inst = Inst::CondBr {
kind: CondBrKind::NotZero(xreg(0)),
taken: target(1),
@@ -1813,17 +1836,17 @@ mod test {
};
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(1));
buf.bind_label(label(1), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(3) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(2));
buf.bind_label(label(2), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(3) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(3));
buf.bind_label(label(3), state.ctrl_plane_mut());
let buf = buf.finish();
let buf = buf.finish(state.ctrl_plane_mut());
assert_eq!(0, buf.total_size());
}
@@ -1831,11 +1854,11 @@ mod test {
fn test_flip_cond() {
let info = EmitInfo::new(settings::Flags::new(settings::builder()));
let mut buf = MachBuffer::new();
let mut state = Default::default();
let mut state = <Inst as MachInstEmit>::State::default();
buf.reserve_labels_for_blocks(4);
buf.bind_label(label(0));
buf.bind_label(label(0), state.ctrl_plane_mut());
let inst = Inst::CondBr {
kind: CondBrKind::Zero(xreg(0)),
taken: target(1),
@@ -1843,19 +1866,19 @@ mod test {
};
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(1));
buf.bind_label(label(1), state.ctrl_plane_mut());
let inst = Inst::Nop4;
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(2));
buf.bind_label(label(2), state.ctrl_plane_mut());
let inst = Inst::Udf {
trap_code: TrapCode::Interrupt,
};
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(3));
buf.bind_label(label(3), state.ctrl_plane_mut());
let buf = buf.finish();
let buf = buf.finish(state.ctrl_plane_mut());
let mut buf2 = MachBuffer::new();
let mut state = Default::default();
@@ -1867,7 +1890,7 @@ mod test {
let inst = Inst::Nop4;
inst.emit(&[], &mut buf2, &info, &mut state);
let buf2 = buf2.finish();
let buf2 = buf2.finish(state.ctrl_plane_mut());
assert_eq!(buf.data, buf2.data);
}
@@ -1876,11 +1899,11 @@ mod test {
fn test_island() {
let info = EmitInfo::new(settings::Flags::new(settings::builder()));
let mut buf = MachBuffer::new();
let mut state = Default::default();
let mut state = <Inst as MachInstEmit>::State::default();
buf.reserve_labels_for_blocks(4);
buf.bind_label(label(0));
buf.bind_label(label(0), state.ctrl_plane_mut());
let inst = Inst::CondBr {
kind: CondBrKind::NotZero(xreg(0)),
taken: target(2),
@@ -1888,24 +1911,24 @@ mod test {
};
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(1));
buf.bind_label(label(1), state.ctrl_plane_mut());
while buf.cur_offset() < 2000000 {
if buf.island_needed(0) {
buf.emit_island(0);
buf.emit_island(0, state.ctrl_plane_mut());
}
let inst = Inst::Nop4;
inst.emit(&[], &mut buf, &info, &mut state);
}
buf.bind_label(label(2));
buf.bind_label(label(2), state.ctrl_plane_mut());
let inst = Inst::Nop4;
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(3));
buf.bind_label(label(3), state.ctrl_plane_mut());
let inst = Inst::Nop4;
inst.emit(&[], &mut buf, &info, &mut state);
let buf = buf.finish();
let buf = buf.finish(state.ctrl_plane_mut());
assert_eq!(2000000 + 8, buf.total_size());
@@ -1934,7 +1957,7 @@ mod test {
};
inst.emit(&[], &mut buf2, &info, &mut state);
let buf2 = buf2.finish();
let buf2 = buf2.finish(state.ctrl_plane_mut());
assert_eq!(&buf.data[0..8], &buf2.data[..]);
}
@@ -1943,25 +1966,25 @@ mod test {
fn test_island_backward() {
let info = EmitInfo::new(settings::Flags::new(settings::builder()));
let mut buf = MachBuffer::new();
let mut state = Default::default();
let mut state = <Inst as MachInstEmit>::State::default();
buf.reserve_labels_for_blocks(4);
buf.bind_label(label(0));
buf.bind_label(label(0), state.ctrl_plane_mut());
let inst = Inst::Nop4;
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(1));
buf.bind_label(label(1), state.ctrl_plane_mut());
let inst = Inst::Nop4;
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(2));
buf.bind_label(label(2), state.ctrl_plane_mut());
while buf.cur_offset() < 2000000 {
let inst = Inst::Nop4;
inst.emit(&[], &mut buf, &info, &mut state);
}
buf.bind_label(label(3));
buf.bind_label(label(3), state.ctrl_plane_mut());
let inst = Inst::CondBr {
kind: CondBrKind::NotZero(xreg(0)),
taken: target(0),
@@ -1969,7 +1992,7 @@ mod test {
};
inst.emit(&[], &mut buf, &info, &mut state);
let buf = buf.finish();
let buf = buf.finish(state.ctrl_plane_mut());
assert_eq!(2000000 + 12, buf.total_size());
@@ -1986,7 +2009,7 @@ mod test {
};
inst.emit(&[], &mut buf2, &info, &mut state);
let buf2 = buf2.finish();
let buf2 = buf2.finish(state.ctrl_plane_mut());
assert_eq!(&buf.data[2000000..], &buf2.data[..]);
}
@@ -2028,11 +2051,11 @@ mod test {
let info = EmitInfo::new(settings::Flags::new(settings::builder()));
let mut buf = MachBuffer::new();
let mut state = Default::default();
let mut state = <Inst as MachInstEmit>::State::default();
buf.reserve_labels_for_blocks(8);
buf.bind_label(label(0));
buf.bind_label(label(0), state.ctrl_plane_mut());
let inst = Inst::CondBr {
kind: CondBrKind::Zero(xreg(0)),
taken: target(1),
@@ -2040,38 +2063,38 @@ mod test {
};
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(1));
buf.bind_label(label(1), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(3) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(2));
buf.bind_label(label(2), state.ctrl_plane_mut());
let inst = Inst::Nop4;
inst.emit(&[], &mut buf, &info, &mut state);
inst.emit(&[], &mut buf, &info, &mut state);
let inst = Inst::Jump { dest: target(0) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(3));
buf.bind_label(label(3), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(4) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(4));
buf.bind_label(label(4), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(5) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(5));
buf.bind_label(label(5), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(7) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(6));
buf.bind_label(label(6), state.ctrl_plane_mut());
let inst = Inst::Nop4;
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(7));
buf.bind_label(label(7), state.ctrl_plane_mut());
let inst = Inst::Ret { rets: vec![] };
inst.emit(&[], &mut buf, &info, &mut state);
let buf = buf.finish();
let buf = buf.finish(state.ctrl_plane_mut());
let golden_data = vec![
0xa0, 0x00, 0x00, 0xb4, // cbz x0, 0x14
@@ -2104,31 +2127,31 @@ mod test {
// b label0
let info = EmitInfo::new(settings::Flags::new(settings::builder()));
let mut buf = MachBuffer::new();
let mut state = Default::default();
let mut state = <Inst as MachInstEmit>::State::default();
buf.reserve_labels_for_blocks(5);
buf.bind_label(label(0));
buf.bind_label(label(0), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(1) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(1));
buf.bind_label(label(1), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(2) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(2));
buf.bind_label(label(2), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(3) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(3));
buf.bind_label(label(3), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(4) };
inst.emit(&[], &mut buf, &info, &mut state);
buf.bind_label(label(4));
buf.bind_label(label(4), state.ctrl_plane_mut());
let inst = Inst::Jump { dest: target(1) };
inst.emit(&[], &mut buf, &info, &mut state);
let buf = buf.finish();
let buf = buf.finish(state.ctrl_plane_mut());
let golden_data = vec![
0x00, 0x00, 0x00, 0x14, // b 0
@@ -2140,10 +2163,11 @@ mod test {
#[test]
fn metadata_records() {
let mut buf = MachBuffer::<Inst>::new();
let ctrl_plane = &mut Default::default();
buf.reserve_labels_for_blocks(1);
buf.bind_label(label(0));
buf.bind_label(label(0), ctrl_plane);
buf.put1(1);
buf.add_trap(TrapCode::HeapOutOfBounds);
buf.put1(2);
@@ -2163,7 +2187,7 @@ mod test {
);
buf.put1(4);
let buf = buf.finish();
let buf = buf.finish(ctrl_plane);
assert_eq!(buf.data(), &[1, 2, 3, 4]);
assert_eq!(

View File

@@ -52,6 +52,7 @@ use crate::settings::Flags;
use crate::value_label::ValueLabelsRanges;
use alloc::vec::Vec;
use core::fmt::Debug;
use cranelift_control::ControlPlane;
use cranelift_entity::PrimaryMap;
use regalloc2::{Allocation, VReg};
use smallvec::{smallvec, SmallVec};
@@ -272,13 +273,21 @@ pub trait MachInstEmit: MachInst {
/// emitting a function body.
pub trait MachInstEmitState<I: VCodeInst>: Default + Clone + Debug {
/// Create a new emission state given the ABI object.
fn new(abi: &Callee<I::ABIMachineSpec>) -> Self;
fn new(abi: &Callee<I::ABIMachineSpec>, ctrl_plane: ControlPlane) -> Self;
/// Update the emission state before emitting an instruction that is a
/// safepoint.
fn pre_safepoint(&mut self, _stack_map: StackMap) {}
/// Update the emission state to indicate instructions are associated with a
/// particular RelSourceLoc.
fn pre_sourceloc(&mut self, _srcloc: RelSourceLoc) {}
/// The emission state holds ownership of a control plane, so it doesn't
/// have to be passed around explicitly too much. `ctrl_plane_mut` may
/// be used if temporary access to the control plane is needed by some
/// other function that doesn't have access to the emission state.
fn ctrl_plane_mut(&mut self) -> &mut ControlPlane;
/// Used to continue using a control plane after the emission state is
/// not needed anymore.
fn take_ctrl_plane(self) -> ControlPlane;
}
/// The result of a `MachBackend::compile_function()` call. Contains machine
@@ -474,7 +483,13 @@ pub trait TextSectionBuilder {
///
/// This function returns the offset at which the data was placed in the
/// text section.
fn append(&mut self, labeled: bool, data: &[u8], align: u32) -> u64;
fn append(
&mut self,
labeled: bool,
data: &[u8],
align: u32,
ctrl_plane: &mut ControlPlane,
) -> u64;
/// Attempts to resolve a relocation for this function.
///
@@ -497,7 +512,7 @@ pub trait TextSectionBuilder {
/// Completes this text section, filling out any final details, and returns
/// the bytes of the text section.
fn finish(&mut self) -> Vec<u8>;
fn finish(&mut self, ctrl_plane: &mut ControlPlane) -> Vec<u8>;
}
/// Expected unwind info type.

View File

@@ -26,6 +26,7 @@ use crate::timing;
use crate::trace;
use crate::CodegenError;
use crate::ValueLocRange;
use cranelift_control::ControlPlane;
use regalloc2::{
Edit, Function as RegallocFunction, InstOrEdit, InstRange, Operand, OperandKind, PRegSet,
RegClass, VReg,
@@ -763,6 +764,7 @@ impl<I: VCodeInst> VCode<I> {
regalloc: &regalloc2::Output,
want_disasm: bool,
want_metadata: bool,
ctrl_plane: &mut ControlPlane,
) -> EmitResult<I>
where
I: VCodeInst,
@@ -813,7 +815,7 @@ impl<I: VCodeInst> VCode<I> {
let mut cur_srcloc = None;
let mut last_offset = None;
let mut inst_offsets = vec![];
let mut state = I::State::new(&self.abi);
let mut state = I::State::new(&self.abi, std::mem::take(ctrl_plane));
let mut disasm = String::new();
@@ -874,7 +876,7 @@ impl<I: VCodeInst> VCode<I> {
// Now emit the regular block body.
buffer.bind_label(MachLabel::from_block(block));
buffer.bind_label(MachLabel::from_block(block), state.ctrl_plane_mut());
if want_disasm {
writeln!(&mut disasm, "block{}:", block.index()).unwrap();
@@ -1054,11 +1056,14 @@ impl<I: VCodeInst> VCode<I> {
let worst_case_next_bb =
I::worst_case_size() * (next_block_size + next_block_ra_insertions);
if buffer.island_needed(worst_case_next_bb) {
buffer.emit_island(worst_case_next_bb);
buffer.emit_island(worst_case_next_bb, ctrl_plane);
}
}
}
// emission state is not needed anymore, move control plane back out
*ctrl_plane = state.take_ctrl_plane();
// Emit the constants used by the function.
let mut alignment = 1;
for (constant, data) in self.constants.iter() {