[WIP] Add a Trap sink to code generation (#279)

* First draft of TrapSink implementation.

* Add trap sink calls to 'trapif' and 'trapff' recipes.

* Add SourceLoc to trap sink calls, and add trap sink calls to all loads and stores.

* Add IntegerDivisionByZero trap to div recipe.

* Only emit load/store traps if 'notrap' flag is not set on the instruction.

* Update filetest machinery to add new trap sink functionality.

* Update filetests to include traps in output.

* Add a few more trap outputs to filetests.

* Add trap output to CLI tool.
This commit is contained in:
Tyler McMullen
2018-03-28 22:48:03 -07:00
committed by Dan Gohman
parent d566faa8fb
commit 951ff11f85
12 changed files with 358 additions and 263 deletions

View File

@@ -14,7 +14,7 @@
//! relocations to a `RelocSink` trait object. Relocations are less frequent than the
//! `CodeSink::put*` methods, so the performance impact of the virtual callbacks is less severe.
use ir::{ExternalName, JumpTable};
use ir::{ExternalName, JumpTable, TrapCode, SourceLoc};
use super::{CodeSink, CodeOffset, Reloc, Addend};
use std::ptr::write_unaligned;
@@ -33,15 +33,21 @@ pub struct MemoryCodeSink<'a> {
data: *mut u8,
offset: isize,
relocs: &'a mut RelocSink,
traps: &'a mut TrapSink,
}
impl<'a> MemoryCodeSink<'a> {
/// Create a new memory code sink that writes a function to the memory pointed to by `data`.
pub fn new(data: *mut u8, relocs: &mut RelocSink) -> MemoryCodeSink {
pub fn new<'sink>(
data: *mut u8,
relocs: &'sink mut RelocSink,
traps: &'sink mut TrapSink,
) -> MemoryCodeSink<'sink> {
MemoryCodeSink {
data,
offset: 0,
relocs,
traps,
}
}
}
@@ -58,6 +64,12 @@ pub trait RelocSink {
fn reloc_jt(&mut self, CodeOffset, Reloc, JumpTable);
}
/// A trait for receiving trap codes and offsets.
pub trait TrapSink {
/// Add trap information for a specific offset.
fn trap(&mut self, CodeOffset, SourceLoc, TrapCode);
}
impl<'a> CodeSink for MemoryCodeSink<'a> {
fn offset(&self) -> CodeOffset {
self.offset as CodeOffset
@@ -105,4 +117,9 @@ impl<'a> CodeSink for MemoryCodeSink<'a> {
let ofs = self.offset();
self.relocs.reloc_jt(ofs, rel, jt);
}
fn trap(&mut self, code: TrapCode, srcloc: SourceLoc) {
let ofs = self.offset();
self.traps.trap(ofs, srcloc, code);
}
}

View File

@@ -8,9 +8,9 @@ mod memorysink;
pub use regalloc::RegDiversions;
pub use self::relaxation::relax_branches;
pub use self::memorysink::{MemoryCodeSink, RelocSink};
pub use self::memorysink::{MemoryCodeSink, RelocSink, TrapSink};
use ir::{ExternalName, JumpTable, Function, Inst};
use ir::{ExternalName, JumpTable, Function, Inst, TrapCode, SourceLoc};
use std::fmt;
/// Offset in bytes from the beginning of the function.
@@ -86,6 +86,9 @@ pub trait CodeSink {
/// Add a relocation referencing a jump table.
fn reloc_jt(&mut self, Reloc, JumpTable);
/// Add trap information for the current offset.
fn trap(&mut self, TrapCode, SourceLoc);
}
/// Report a bad encoding error.

View File

@@ -9,7 +9,7 @@
//! contexts concurrently. Typically, you would have one context per compilation thread and only a
//! single ISA instance.
use binemit::{CodeOffset, relax_branches, MemoryCodeSink, RelocSink};
use binemit::{CodeOffset, relax_branches, MemoryCodeSink, RelocSink, TrapSink};
use dominator_tree::DominatorTree;
use flowgraph::ControlFlowGraph;
use ir::Function;
@@ -111,9 +111,15 @@ impl Context {
/// code is returned by `compile` above.
///
/// The machine code is not relocated. Instead, any relocations are emitted into `relocs`.
pub fn emit_to_memory(&self, mem: *mut u8, relocs: &mut RelocSink, isa: &TargetIsa) {
pub fn emit_to_memory(
&self,
mem: *mut u8,
relocs: &mut RelocSink,
traps: &mut TrapSink,
isa: &TargetIsa,
) {
let _tt = timing::binemit();
isa.emit_function(&self.func, &mut MemoryCodeSink::new(mem, relocs));
isa.emit_function(&self.func, &mut MemoryCodeSink::new(mem, relocs, traps));
}
/// Run the verifier on the function.

View File

@@ -1,7 +1,7 @@
//! Emitting binary Intel machine code.
use binemit::{CodeSink, Reloc, bad_encoding};
use ir::{Function, Inst, Ebb, InstructionData, Opcode};
use ir::{Function, Inst, Ebb, InstructionData, Opcode, TrapCode};
use ir::condcodes::{CondCode, IntCC, FloatCC};
use isa::{RegUnit, StackRef, StackBase, StackBaseMask};
use regalloc::RegDiversions;