Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MachInst backend: pass through SourceLoc information. #1575

Merged
merged 1 commit into from
Apr 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cranelift/codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ gimli = { version = "0.20.0", default-features = false, features = ["write"], op
smallvec = { version = "1.0.0" }
thiserror = "1.0.4"
byteorder = { version = "1.3.2", default-features = false }
regalloc = "0.0.17"
regalloc = "0.0.18"
# It is a goal of the cranelift-codegen crate to have minimal external dependencies.
# Please don't add any unless they are essential to the task of creating binary
# machine code. Integration tests that need external dependencies can be
Expand Down
3 changes: 3 additions & 0 deletions cranelift/codegen/src/machinst/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
"lower_branch_group: targets = {:?} branches = {:?}",
targets, branches
);
self.vcode.set_srcloc(self.srcloc(branches[0]));
backend.lower_branch_group(
&mut self,
&branches[..],
Expand All @@ -361,6 +362,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
let num_uses = self.num_uses[inst];
let side_effect = has_side_effect(self.f, inst);
if side_effect || num_uses > 0 {
self.vcode.set_srcloc(self.srcloc(inst));
backend.lower(&mut self, inst);
self.vcode.end_ir_inst();
} else {
Expand Down Expand Up @@ -389,6 +391,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
"lower_branch_group: targets = {:?} branches = {:?}",
targets, branches
);
self.vcode.set_srcloc(self.srcloc(branches[0]));
backend.lower_branch_group(&mut self, &branches[..], &targets[..], fallthrough);
self.vcode.end_ir_inst();
branches.clear();
Expand Down
1 change: 0 additions & 1 deletion cranelift/codegen/src/machinst/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
//! ```

use crate::binemit::{CodeInfo, CodeOffset};
use crate::entity::SecondaryMap;
use crate::ir::condcodes::IntCC;
use crate::ir::{Function, Type};
use crate::result::CodegenResult;
Expand Down
108 changes: 107 additions & 1 deletion cranelift/codegen/src/machinst/sections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ impl MachSections {
sink.end_codegen();
}

/// Get a list of source location mapping tuples in sorted-by-start-offset order.
pub fn get_srclocs_sorted<'a>(&'a self) -> MachSectionsSrcLocs<'a> {
MachSectionsSrcLocs::new(&self.sections)
}

/// Get the total required size for these sections.
pub fn total_size(&self) -> CodeOffset {
if self.sections.len() == 0 {
Expand All @@ -90,6 +95,58 @@ impl MachSections {
}
}

/// An iterator over the srclocs in each section.
/// Returns MachSrcLocs in an order sorted by start location.
pub struct MachSectionsSrcLocs<'a> {
sections: &'a [MachSection],
cur_section: usize,
cur_srcloc: usize,
// For validation:
last_offset: CodeOffset,
}

impl<'a> MachSectionsSrcLocs<'a> {
fn new(sections: &'a [MachSection]) -> MachSectionsSrcLocs<'a> {
MachSectionsSrcLocs {
sections,
cur_section: 0,
cur_srcloc: 0,
last_offset: 0,
}
}
}

impl<'a> Iterator for MachSectionsSrcLocs<'a> {
type Item = &'a MachSrcLoc;

fn next(&mut self) -> Option<&'a MachSrcLoc> {
// We simply iterate through sections and srcloc records in order. This produces a
// sorted order naturally because sections are in starting-offset-order, and srclocs
// are produced as a section is emitted into, so are in order as well.

// If we're out of sections, we're done.
if self.cur_section >= self.sections.len() {
return None;
}

// Otherwise, make sure we have a srcloc in the current section left to return, and
// advance to the next section if not. Done if we run out of sections.
while self.cur_srcloc >= self.sections[self.cur_section].srclocs.len() {
self.cur_srcloc = 0;
self.cur_section += 1;
if self.cur_section >= self.sections.len() {
return None;
}
}

let loc = &self.sections[self.cur_section].srclocs[self.cur_srcloc];
self.cur_srcloc += 1;
debug_assert!(loc.start >= self.last_offset);
self.last_offset = loc.start;
Some(loc)
}
}

/// An abstraction over MachSection and MachSectionSize: some
/// receiver of section data.
pub trait MachSectionOutput {
Expand Down Expand Up @@ -143,6 +200,12 @@ pub trait MachSectionOutput {
/// Add a call return address record at the current offset.
fn add_call_site(&mut self, loc: SourceLoc, opcode: Opcode);

/// Start the output for the given source-location at the current offset.
fn start_srcloc(&mut self, loc: SourceLoc);

/// End the output for the previously-given source-location at the current offset.
fn end_srcloc(&mut self);

/// Align up to the given alignment.
fn align_to(&mut self, align_to: CodeOffset) {
assert!(align_to.is_power_of_two());
Expand All @@ -168,8 +231,13 @@ pub struct MachSection {
pub relocs: Vec<MachReloc>,
/// Any trap records referring to this section.
pub traps: Vec<MachTrap>,
/// Any call site record referring to this section.
/// Any call site records referring to this section.
pub call_sites: Vec<MachCallSite>,
/// Any source location mappings referring to this section.
pub srclocs: Vec<MachSrcLoc>,
/// The current source location in progress (after `start_srcloc()` and before `end_srcloc()`).
/// This is a (start_offset, src_loc) tuple.
pub cur_srcloc: Option<(CodeOffset, SourceLoc)>,
}

impl MachSection {
Expand All @@ -182,6 +250,8 @@ impl MachSection {
relocs: vec![],
traps: vec![],
call_sites: vec![],
srclocs: vec![],
cur_srcloc: None,
}
}

Expand Down Expand Up @@ -266,6 +336,23 @@ impl MachSectionOutput for MachSection {
opcode,
});
}

fn start_srcloc(&mut self, loc: SourceLoc) {
self.cur_srcloc = Some((self.cur_offset_from_start(), loc));
}

fn end_srcloc(&mut self) {
let (start, loc) = self
.cur_srcloc
.take()
.expect("end_srcloc() called without start_srcloc()");
let end = self.cur_offset_from_start();
// Skip zero-length extends.
debug_assert!(end >= start);
if end > start {
self.srclocs.push(MachSrcLoc { start, end, loc });
}
}
}

/// A MachSectionOutput implementation that records only size.
Expand Down Expand Up @@ -315,6 +402,10 @@ impl MachSectionOutput for MachSectionSize {
fn add_trap(&mut self, _: SourceLoc, _: TrapCode) {}

fn add_call_site(&mut self, _: SourceLoc, _: Opcode) {}

fn start_srcloc(&mut self, _: SourceLoc) {}

fn end_srcloc(&mut self) {}
}

/// A relocation resulting from a compilation.
Expand Down Expand Up @@ -352,3 +443,18 @@ pub struct MachCallSite {
/// The call's opcode.
pub opcode: Opcode,
}

/// A source-location mapping resulting from a compilation.
#[derive(Clone, Debug)]
pub struct MachSrcLoc {
/// The start of the region of code corresponding to a source location.
/// This is relative to the start of the function, not to the start of the
/// section.
pub start: CodeOffset,
/// The end of the region of code corresponding to a source location.
/// This is relative to the start of the section, not to the start of the
/// section.
pub end: CodeOffset,
/// The source location.
pub loc: SourceLoc,
}
Loading