Add source location support to FuncCursor and EncCursor.

A cursor now also remembers a current source location which will be
assigned to all new instructions created with the cursor.

The old layout::Cursor can't support source locations because it doesn't
have a reference to the full ir::Function.
This commit is contained in:
Jakob Stoklund Olesen
2017-09-21 10:38:11 -07:00
parent b2a314a229
commit 4d4da2dc60
9 changed files with 143 additions and 38 deletions

View File

@@ -358,6 +358,7 @@ def gen_xform_group(xgrp, fmt, type_sets):
'cfg: &mut ::flowgraph::ControlFlowGraph) -> '
'bool {{'.format(xgrp.name), '}'):
fmt.line('use ir::{InstBuilder, CursorBase};')
fmt.line('let srcloc = func.srclocs[inst];')
# Group the xforms by opcode so we can generate a big switch.
# Preserve ordering.
@@ -372,8 +373,9 @@ def gen_xform_group(xgrp, fmt, type_sets):
with fmt.indented(
'ir::Opcode::{} => {{'.format(camel_name), '}'):
fmt.line(
'let pos = &mut '
'ir::Cursor::new(&mut func.layout)'
'let pos = &mut ir::Cursor::new'
'(&mut func.layout, &mut func.srclocs)'
'.with_srcloc(srcloc)'
'.at_inst(inst);')
fmt.line('let dfg = &mut func.dfg;')
for xform in xforms[camel_name]:

View File

@@ -19,6 +19,7 @@ pub use ir::layout::Cursor as LayoutCursor;
/// encoding.
pub struct FuncCursor<'f> {
pos: CursorPosition,
srcloc: ir::SourceLoc,
/// The referenced function.
pub func: &'f mut ir::Function,
@@ -29,10 +30,16 @@ impl<'f> FuncCursor<'f> {
pub fn new(func: &'f mut ir::Function) -> FuncCursor<'f> {
FuncCursor {
pos: CursorPosition::Nowhere,
srcloc: Default::default(),
func,
}
}
/// Use the source location of `inst` for future instructions.
pub fn use_srcloc(&mut self, inst: ir::Inst) {
self.srcloc = self.func.srclocs[inst];
}
/// Create an instruction builder that inserts an instruction at the current position.
pub fn ins(&mut self) -> ir::InsertBuilder<&mut FuncCursor<'f>> {
ir::InsertBuilder::new(self)
@@ -48,6 +55,14 @@ impl<'f> Cursor for FuncCursor<'f> {
self.pos = pos
}
fn srcloc(&self) -> ir::SourceLoc {
self.srcloc
}
fn set_srcloc(&mut self, srcloc: ir::SourceLoc) {
self.srcloc = srcloc;
}
fn layout(&self) -> &ir::Layout {
&self.func.layout
}
@@ -68,6 +83,9 @@ impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut FuncCursor<'f> {
fn insert_built_inst(self, inst: ir::Inst, _: ir::Type) -> &'c mut ir::DataFlowGraph {
self.insert_inst(inst);
if !self.srcloc.is_default() {
self.func.srclocs[inst] = self.srcloc;
}
&mut self.func.dfg
}
}
@@ -80,6 +98,7 @@ impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut FuncCursor<'f> {
/// public `pos.func` member.
pub struct EncCursor<'f> {
pos: CursorPosition,
srcloc: ir::SourceLoc,
built_inst: Option<ir::Inst>,
/// The referenced function.
@@ -94,12 +113,18 @@ impl<'f> EncCursor<'f> {
pub fn new(func: &'f mut ir::Function, isa: &'f TargetIsa) -> EncCursor<'f> {
EncCursor {
pos: CursorPosition::Nowhere,
srcloc: Default::default(),
built_inst: None,
func,
isa,
}
}
/// Use the source location of `inst` for future instructions.
pub fn use_srcloc(&mut self, inst: ir::Inst) {
self.srcloc = self.func.srclocs[inst];
}
/// Create an instruction builder that will insert an encoded instruction at the current
/// position.
///
@@ -134,6 +159,14 @@ impl<'f> Cursor for EncCursor<'f> {
self.pos = pos
}
fn srcloc(&self) -> ir::SourceLoc {
self.srcloc
}
fn set_srcloc(&mut self, srcloc: ir::SourceLoc) {
self.srcloc = srcloc;
}
fn layout(&self) -> &ir::Layout {
&self.func.layout
}
@@ -161,6 +194,10 @@ impl<'c, 'f> ir::InstInserterBase<'c> for &'c mut EncCursor<'f> {
self.insert_inst(inst);
self.built_inst = Some(inst);
if !self.srcloc.is_default() {
self.func.srclocs[inst] = self.srcloc;
}
// Assign an encoding.
match self.isa.encode(
&self.func.dfg,

View File

@@ -7,7 +7,7 @@ use std::cmp;
use std::iter::{Iterator, IntoIterator};
use entity::EntityMap;
use packed_option::PackedOption;
use ir::{Ebb, Inst, Type, DataFlowGraph};
use ir::{Ebb, Inst, Type, DataFlowGraph, SourceLoc, SourceLocs};
use ir::builder::InstInserterBase;
use ir::progpoint::{ProgramOrder, ExpandedProgramPoint};
@@ -676,7 +676,10 @@ impl<'f> DoubleEndedIterator for Insts<'f> {
pub struct Cursor<'f> {
/// Borrowed function layout. Public so it can be re-borrowed from this cursor.
pub layout: &'f mut Layout,
/// Borrowed source locations.
pub srclocs: Option<&'f mut SourceLocs>,
pos: CursorPosition,
srcloc: SourceLoc,
}
/// The possible positions of a cursor.
@@ -703,12 +706,39 @@ pub trait CursorBase {
/// Set the current position.
fn set_position(&mut self, pos: CursorPosition);
/// Get the source location that should be assigned to new instructions.
fn srcloc(&self) -> SourceLoc;
/// Set the source location that should be assigned to new instructions.
fn set_srcloc(&mut self, srcloc: SourceLoc);
/// Borrow a reference to the function layout that this cursor is navigating.
fn layout(&self) -> &Layout;
/// Borrow a mutable reference to the function layout that this cursor is navigating.
fn layout_mut(&mut self) -> &mut Layout;
/// Exchange this cursor for one with a set source location.
///
/// This is intended to be used as a builder method:
///
/// ```
/// # use cretonne::ir::{Function, Ebb, SourceLoc};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function, srcloc: SourceLoc) {
/// let mut pos = FuncCursor::new(func).with_srcloc(srcloc);
///
/// // Use `pos`...
/// }
/// ```
fn with_srcloc(mut self, srcloc: SourceLoc) -> Self
where
Self: Sized,
{
self.set_srcloc(srcloc);
self
}
/// Rebuild this cursor positioned at `pos`.
fn at_position(mut self, pos: CursorPosition) -> Self
where
@@ -724,9 +754,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb, Inst};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function, inst: Inst) {
/// let mut pos = Cursor::new(&mut func.layout).at_inst(inst);
/// let mut pos = FuncCursor::new(func).at_inst(inst);
///
/// // Use `pos`...
/// }
@@ -747,9 +777,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb, Inst};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function, ebb: Ebb) {
/// let mut pos = Cursor::new(&mut func.layout).at_first_insertion_point(ebb);
/// let mut pos = FuncCursor::new(func).at_first_insertion_point(ebb);
///
/// // Use `pos`...
/// }
@@ -768,9 +798,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb, Inst};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function, ebb: Ebb) {
/// let mut pos = Cursor::new(&mut func.layout).at_first_inst(ebb);
/// let mut pos = FuncCursor::new(func).at_first_inst(ebb);
///
/// // Use `pos`...
/// }
@@ -789,9 +819,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb, Inst};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function, ebb: Ebb) {
/// let mut pos = Cursor::new(&mut func.layout).at_last_inst(ebb);
/// let mut pos = FuncCursor::new(func).at_last_inst(ebb);
///
/// // Use `pos`...
/// }
@@ -810,9 +840,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb, Inst};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function, inst: Inst) {
/// let mut pos = Cursor::new(&mut func.layout).after_inst(inst);
/// let mut pos = FuncCursor::new(func).after_inst(inst);
///
/// // Use `pos`...
/// }
@@ -831,9 +861,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb, Inst};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function, ebb: Ebb) {
/// let mut pos = Cursor::new(&mut func.layout).at_top(ebb);
/// let mut pos = FuncCursor::new(func).at_top(ebb);
///
/// // Use `pos`...
/// }
@@ -852,9 +882,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb, Inst};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function, ebb: Ebb) {
/// let mut pos = Cursor::new(&mut func.layout).at_bottom(ebb);
/// let mut pos = FuncCursor::new(func).at_bottom(ebb);
///
/// // Use `pos`...
/// }
@@ -957,9 +987,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function) {
/// let mut cursor = Cursor::new(&mut func.layout);
/// let mut cursor = FuncCursor::new(func);
/// while let Some(ebb) = cursor.next_ebb() {
/// // Edit ebb.
/// }
@@ -990,9 +1020,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function) {
/// let mut cursor = Cursor::new(&mut func.layout);
/// let mut cursor = FuncCursor::new(func);
/// while let Some(ebb) = cursor.prev_ebb() {
/// // Edit ebb.
/// }
@@ -1027,9 +1057,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_ebb(func: &mut Function, ebb: Ebb) {
/// let mut cursor = Cursor::new(&mut func.layout).at_top(ebb);
/// let mut cursor = FuncCursor::new(func).at_top(ebb);
/// while let Some(inst) = cursor.next_inst() {
/// // Edit instructions...
/// }
@@ -1041,9 +1071,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_func(func: &mut Function) {
/// let mut cursor = Cursor::new(&mut func.layout);
/// let mut cursor = FuncCursor::new(func);
/// while let Some(ebb) = cursor.next_ebb() {
/// while let Some(inst) = cursor.next_inst() {
/// // Edit instructions...
@@ -1095,9 +1125,9 @@ pub trait CursorBase {
///
/// ```
/// # use cretonne::ir::{Function, Ebb};
/// # use cretonne::ir::layout::{Cursor, CursorBase};
/// # use cretonne::cursor::{Cursor, FuncCursor};
/// fn edit_ebb(func: &mut Function, ebb: Ebb) {
/// let mut cursor = Cursor::new(&mut func.layout).at_bottom(ebb);
/// let mut cursor = FuncCursor::new(func).at_bottom(ebb);
/// while let Some(inst) = cursor.prev_inst() {
/// // Edit instructions...
/// }
@@ -1213,6 +1243,14 @@ impl<'f> CursorBase for Cursor<'f> {
self.pos = pos;
}
fn srcloc(&self) -> SourceLoc {
self.srcloc
}
fn set_srcloc(&mut self, srcloc: SourceLoc) {
self.srcloc = srcloc
}
fn layout(&self) -> &Layout {
self.layout
}
@@ -1225,10 +1263,22 @@ impl<'f> CursorBase for Cursor<'f> {
impl<'f> Cursor<'f> {
/// Create a new `Cursor` for `layout`.
/// The cursor holds a mutable reference to `layout` for its entire lifetime.
pub fn new(layout: &'f mut Layout) -> Cursor {
pub fn new<SL: Into<Option<&'f mut SourceLocs>>>(
layout: &'f mut Layout,
srclocs: SL,
) -> Cursor<'f> {
Cursor {
layout,
srclocs: srclocs.into(),
pos: CursorPosition::Nowhere,
srcloc: Default::default(),
}
}
/// Use the source location of `inst` for future instructions.
pub fn use_srcloc(&mut self, inst: Inst) {
if let Some(ref mut ss) = self.srclocs {
self.srcloc = ss[inst];
}
}
}
@@ -1263,6 +1313,13 @@ impl<'c, 'fc: 'c, 'fd> InstInserterBase<'fd> for LayoutCursorInserter<'c, 'fc, '
fn insert_built_inst(self, inst: Inst, _ctrl_typevar: Type) -> &'fd mut DataFlowGraph {
self.pos.insert_inst(inst);
if !self.pos.srcloc.is_default() {
if let Some(ref mut ss) = self.pos.srclocs {
ss[inst] = self.pos.srcloc;
} else {
panic!("layout::Cursor missing a SourceLocs reference");
}
}
self.dfg
}
}
@@ -1300,7 +1357,7 @@ mod tests {
}
// Check backwards linkage with a cursor.
let mut cur = Cursor::new(layout);
let mut cur = Cursor::new(layout, None);
for &(ebb, insts) in ebbs.into_iter().rev() {
assert_eq!(cur.prev_ebb(), Some(ebb));
for &inst in insts.into_iter().rev() {
@@ -1356,7 +1413,7 @@ mod tests {
}
// Test cursor positioning.
let mut cur = Cursor::new(&mut layout);
let mut cur = Cursor::new(&mut layout, None);
assert_eq!(cur.position(), CursorPosition::Nowhere);
assert_eq!(cur.next_inst(), None);
assert_eq!(cur.position(), CursorPosition::Nowhere);
@@ -1474,7 +1531,7 @@ mod tests {
verify(&mut layout, &[(e1, &[i1, i2, i0])]);
// Test cursor positioning.
let mut cur = Cursor::new(&mut layout).at_top(e1);
let mut cur = Cursor::new(&mut layout, None).at_top(e1);
assert_eq!(cur.position(), CursorPosition::Before(e1));
assert_eq!(cur.prev_inst(), None);
assert_eq!(cur.position(), CursorPosition::Before(e1));
@@ -1594,7 +1651,7 @@ mod tests {
assert_eq!(layout.inst_ebb(i0), Some(e1));
{
let mut cur = Cursor::new(&mut layout);
let mut cur = Cursor::new(&mut layout, None);
assert_eq!(cur.next_ebb(), Some(e0));
assert_eq!(cur.next_inst(), None);
assert_eq!(cur.next_ebb(), Some(e1));
@@ -1622,7 +1679,7 @@ mod tests {
assert_eq!(layout.inst_ebb(i3), Some(e2));
{
let mut cur = Cursor::new(&mut layout);
let mut cur = Cursor::new(&mut layout, None);
assert_eq!(cur.next_ebb(), Some(e0));
assert_eq!(cur.next_inst(), Some(i1));
assert_eq!(cur.next_inst(), None);

View File

@@ -62,7 +62,7 @@ fn legalize_entry_arguments(func: &mut Function, entry: Ebb) {
// Insert position for argument conversion code.
// We want to insert instructions before the first instruction in the entry block.
// If the entry block is empty, append instructions to it instead.
let mut pos = Cursor::new(&mut func.layout).at_first_inst(entry);
let mut pos = Cursor::new(&mut func.layout, &mut func.srclocs).at_first_inst(entry);
// Keep track of the argument types in the ABI-legalized signature.
let abi_types = &func.signature.argument_types;
@@ -488,7 +488,8 @@ fn legalize_inst_arguments<ArgType>(
/// Returns `true` if any instructions were inserted.
pub fn handle_call_abi(mut inst: Inst, func: &mut Function, cfg: &ControlFlowGraph) -> bool {
let dfg = &mut func.dfg;
let pos = &mut Cursor::new(&mut func.layout).at_inst(inst);
let pos = &mut Cursor::new(&mut func.layout, &mut func.srclocs).at_inst(inst);
pos.use_srcloc(inst);
// Start by checking if the argument types already match the signature.
let sig_ref = match check_call_signature(dfg, inst) {
@@ -530,7 +531,8 @@ pub fn handle_call_abi(mut inst: Inst, func: &mut Function, cfg: &ControlFlowGra
pub fn handle_return_abi(inst: Inst, func: &mut Function, cfg: &ControlFlowGraph) -> bool {
let dfg = &mut func.dfg;
let sig = &mut func.signature;
let pos = &mut Cursor::new(&mut func.layout).at_inst(inst);
let pos = &mut Cursor::new(&mut func.layout, &mut func.srclocs).at_inst(inst);
pos.use_srcloc(inst);
// Check if the returned types already match the signature.
if check_return_signature(dfg, inst, sig) {

View File

@@ -51,6 +51,7 @@ fn deref_addr(inst: ir::Inst, func: &mut ir::Function, base: ir::GlobalVar, offs
// detects any cycles in the `deref` globals.
let ptr_ty = func.dfg.value_type(func.dfg.first_result(inst));
let mut pos = FuncCursor::new(func).at_inst(inst);
pos.use_srcloc(inst);
let base_addr = pos.ins().global_addr(ptr_ty, base);
// TODO: We could probably set both `notrap` and `aligned` on this load instruction.

View File

@@ -48,6 +48,7 @@ fn dynamic_addr(
let addr_ty = func.dfg.value_type(func.dfg.first_result(inst));
let min_size = func.heaps[heap].min_size.into();
let mut pos = FuncCursor::new(func).at_inst(inst);
pos.use_srcloc(inst);
// Start with the bounds check. Trap if `offset + size > bound`.
let bound_addr = pos.ins().global_addr(addr_ty, bound_gv);
@@ -99,6 +100,7 @@ fn static_addr(
let offset_ty = func.dfg.value_type(offset);
let addr_ty = func.dfg.value_type(func.dfg.first_result(inst));
let mut pos = FuncCursor::new(func).at_inst(inst);
pos.use_srcloc(inst);
// Start with the bounds check. Trap if `offset + size > bound`.
if size > bound {
@@ -147,6 +149,7 @@ fn offset_addr(
func: &mut ir::Function,
) {
let mut pos = FuncCursor::new(func).at_inst(inst);
pos.use_srcloc(inst);
// Convert `offset` to `addr_ty`.
if offset_ty != addr_ty {

View File

@@ -138,6 +138,7 @@ fn expand_cond_trap(inst: ir::Inst, func: &mut ir::Function, cfg: &mut ControlFl
}
let mut pos = FuncCursor::new(func).after_inst(inst);
pos.use_srcloc(inst);
pos.ins().trap(code);
pos.insert_ebb(new_ebb);
@@ -154,6 +155,7 @@ fn expand_fconst(inst: ir::Inst, func: &mut ir::Function, _cfg: &mut ControlFlow
// In the future, we may want to generate constant pool entries for these constants, but for
// now use an `iconst` and a bit cast.
let mut pos = FuncCursor::new(func).at_inst(inst);
pos.use_srcloc(inst);
let ival = match pos.func.dfg[inst] {
ir::InstructionData::UnaryIeee32 {
opcode: ir::Opcode::F32const,

View File

@@ -120,7 +120,7 @@ fn split_any(
concat: Opcode,
) -> (Value, Value) {
let mut repairs = Vec::new();
let mut pos = ir::Cursor::new(layout).at_position(pos);
let mut pos = ir::Cursor::new(layout, None).at_position(pos);
let result = split_value(dfg, &mut pos, value, concat, &mut repairs);
// We have split the value requested, and now we may need to fix some EBB predecessors.

View File

@@ -148,8 +148,9 @@ impl<'a> Context<'a> {
self.divert.clear();
// Now go through the instructions in `ebb` and color the values they define.
let mut pos = Cursor::new(&mut func.layout).at_top(ebb);
let mut pos = Cursor::new(&mut func.layout, &mut func.srclocs).at_top(ebb);
while let Some(inst) = pos.next_inst() {
pos.use_srcloc(inst);
if let Some(constraints) = self.encinfo.operand_constraints(func.encodings[inst]) {
self.visit_inst(
inst,