Make the CFG metadata computation conditional on a flag.

This commit is contained in:
Chris Fallin
2021-05-24 11:16:57 -07:00
parent 11a2ef01e7
commit 800cf25bb5
4 changed files with 49 additions and 22 deletions

View File

@@ -245,6 +245,21 @@ pub(crate) fn define() -> SettingGroup {
true, true,
); );
settings.add_bool(
"machine_code_cfg_info",
"Generate CFG metadata for machine code.",
r#"
This increases metadata size and compile time, but allows for the
embedder to more easily post-process or analyze the generated
machine code. It provides code offsets for the start of each
basic block in the generated machine code, and a list of CFG
edges (with blocks identified by start offsets) between them.
This is useful for, e.g., machine-code analyses that verify certain
properties of the generated code.
"#,
false,
);
// BaldrMonkey requires that not-yet-relocated function addresses be encoded // BaldrMonkey requires that not-yet-relocated function addresses be encoded
// as all-ones bitpatterns. // as all-ones bitpatterns.
settings.add_bool( settings.add_bool(

View File

@@ -341,10 +341,16 @@ pub struct MachCompileResult {
/// Debug info: stackslots to stack pointer offsets. /// Debug info: stackslots to stack pointer offsets.
pub stackslot_offsets: PrimaryMap<StackSlot, u32>, pub stackslot_offsets: PrimaryMap<StackSlot, u32>,
/// Basic-block layout info: block start offsets. /// Basic-block layout info: block start offsets.
///
/// This info is generated only if the `machine_code_cfg_info`
/// flag is set.
pub bb_starts: Vec<CodeOffset>, pub bb_starts: Vec<CodeOffset>,
/// Basic-block layout info: block edges. Each edge is `(from, /// Basic-block layout info: block edges. Each edge is `(from,
/// to)`, where `from` and `to` are basic-block start offsets of /// to)`, where `from` and `to` are basic-block start offsets of
/// the respective blocks. /// the respective blocks.
///
/// This info is generated only if the `machine_code_cfg_info`
/// flag is set.
pub bb_edges: Vec<(CodeOffset, CodeOffset)>, pub bb_edges: Vec<(CodeOffset, CodeOffset)>,
} }

View File

@@ -486,6 +486,7 @@ impl<I: VCodeInst> VCode<I> {
let _tt = timing::vcode_emit(); let _tt = timing::vcode_emit();
let mut buffer = MachBuffer::new(); let mut buffer = MachBuffer::new();
let mut state = I::State::new(&*self.abi); let mut state = I::State::new(&*self.abi);
let cfg_metadata = self.flags().machine_code_cfg_info();
let mut bb_starts: Vec<Option<CodeOffset>> = vec![]; let mut bb_starts: Vec<Option<CodeOffset>> = vec![];
// The first M MachLabels are reserved for block indices, the next N MachLabels for // The first M MachLabels are reserved for block indices, the next N MachLabels for
@@ -513,19 +514,21 @@ impl<I: VCodeInst> VCode<I> {
buffer.bind_label(MachLabel::from_block(block)); buffer.bind_label(MachLabel::from_block(block));
label_insn_iix[block as usize] = start; label_insn_iix[block as usize] = start;
// Track BB starts. If we have backed up due to MachBuffer if cfg_metadata {
// branch opts, note that the removed blocks were removed. // Track BB starts. If we have backed up due to MachBuffer
let cur_offset = buffer.cur_offset(); // branch opts, note that the removed blocks were removed.
if last_offset.is_some() && cur_offset <= last_offset.unwrap() { let cur_offset = buffer.cur_offset();
for i in (0..bb_starts.len()).rev() { if last_offset.is_some() && cur_offset <= last_offset.unwrap() {
if bb_starts[i].is_some() && cur_offset > bb_starts[i].unwrap() { for i in (0..bb_starts.len()).rev() {
break; if bb_starts[i].is_some() && cur_offset > bb_starts[i].unwrap() {
break;
}
bb_starts[i] = None;
} }
bb_starts[i] = None;
} }
bb_starts.push(Some(cur_offset));
last_offset = Some(cur_offset);
} }
bb_starts.push(Some(cur_offset));
last_offset = Some(cur_offset);
for iix in start..end { for iix in start..end {
let srcloc = self.srclocs[iix as usize]; let srcloc = self.srclocs[iix as usize];
@@ -606,19 +609,21 @@ impl<I: VCodeInst> VCode<I> {
// Create `bb_edges` and final (filtered) `bb_starts`. // Create `bb_edges` and final (filtered) `bb_starts`.
let mut final_bb_starts = vec![]; let mut final_bb_starts = vec![];
let mut bb_edges = vec![]; let mut bb_edges = vec![];
for block in 0..self.num_blocks() { if cfg_metadata {
if bb_starts[block].is_none() { for block in 0..self.num_blocks() {
// Block was deleted by MachBuffer; skip. if bb_starts[block].is_none() {
continue; // Block was deleted by MachBuffer; skip.
} continue;
let from = bb_starts[block].unwrap(); }
let from = bb_starts[block].unwrap();
final_bb_starts.push(from); final_bb_starts.push(from);
// Resolve each `succ` label and add edges. // Resolve each `succ` label and add edges.
let succs = self.block_succs(BlockIx::new(block as u32)); let succs = self.block_succs(BlockIx::new(block as u32));
for succ in succs.iter() { for succ in succs.iter() {
let to = buffer.resolve_label_offset(MachLabel::from_block(succ.get())); let to = buffer.resolve_label_offset(MachLabel::from_block(succ.get()));
bb_edges.push((from, to)); bb_edges.push((from, to));
}
} }
} }

View File

@@ -511,6 +511,7 @@ enable_atomics = true
enable_safepoints = false enable_safepoints = false
enable_llvm_abi_extensions = false enable_llvm_abi_extensions = false
unwind_info = true unwind_info = true
machine_code_cfg_info = false
emit_all_ones_funcaddrs = false emit_all_ones_funcaddrs = false
enable_probestack = true enable_probestack = true
probestack_func_adjusts_sp = false probestack_func_adjusts_sp = false